diff --git a/include/__config b/include/__config index f141f4f1b7f9..c0b1ef201c05 100644 --- a/include/__config +++ b/include/__config @@ -1,829 +1,831 @@ // -*- C++ -*- //===--------------------------- __config ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_CONFIG #define _LIBCPP_CONFIG #if defined(_MSC_VER) && !defined(__clang__) #define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #endif #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header #endif #ifdef __cplusplus #ifdef __GNUC__ #define _GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__) #else #define _GNUC_VER 0 #endif #define _LIBCPP_VERSION 3800 #ifndef _LIBCPP_ABI_VERSION #define _LIBCPP_ABI_VERSION 1 #endif #if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2 // Change short string represention so that string data starts at offset 0, // improving its alignment in some cases. #define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT // Fix deque iterator type in order to support incomplete types. #define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +// Fix undefined behavior in how std::list stores it's linked nodes. +#define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB #endif #define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y #define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) #define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION) #ifndef __has_attribute #define __has_attribute(__x) 0 #endif #ifndef __has_builtin #define __has_builtin(__x) 0 #endif #ifndef __has_extension #define __has_extension(__x) 0 #endif #ifndef __has_feature #define __has_feature(__x) 0 #endif // '__is_identifier' returns '0' if '__x' is a reserved identifier provided by // the compiler and '1' otherwise. #ifndef __is_identifier #define __is_identifier(__x) 1 #endif #ifdef __LITTLE_ENDIAN__ #if __LITTLE_ENDIAN__ #define _LIBCPP_LITTLE_ENDIAN 1 #define _LIBCPP_BIG_ENDIAN 0 #endif // __LITTLE_ENDIAN__ #endif // __LITTLE_ENDIAN__ #ifdef __BIG_ENDIAN__ #if __BIG_ENDIAN__ #define _LIBCPP_LITTLE_ENDIAN 0 #define _LIBCPP_BIG_ENDIAN 1 #endif // __BIG_ENDIAN__ #endif // __BIG_ENDIAN__ #ifdef __BYTE_ORDER__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define _LIBCPP_LITTLE_ENDIAN 1 #define _LIBCPP_BIG_ENDIAN 0 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define _LIBCPP_LITTLE_ENDIAN 0 #define _LIBCPP_BIG_ENDIAN 1 #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #endif // __BYTE_ORDER__ #ifdef __FreeBSD__ # include # if _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 1 # define _LIBCPP_BIG_ENDIAN 0 # else // _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 0 # define _LIBCPP_BIG_ENDIAN 1 # endif // _BYTE_ORDER == _LITTLE_ENDIAN # ifndef __LONG_LONG_SUPPORTED # define _LIBCPP_HAS_NO_LONG_LONG # endif // __LONG_LONG_SUPPORTED #endif // __FreeBSD__ #ifdef __NetBSD__ # include # if _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 1 # define _LIBCPP_BIG_ENDIAN 0 # else // _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 0 # define _LIBCPP_BIG_ENDIAN 1 # endif // _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_HAS_QUICK_EXIT #endif // __NetBSD__ #ifdef _WIN32 # define _LIBCPP_LITTLE_ENDIAN 1 # define _LIBCPP_BIG_ENDIAN 0 // Compiler intrinsics (MSVC) #if defined(_MSC_VER) && _MSC_VER >= 1400 # define _LIBCPP_HAS_IS_BASE_OF # endif # if defined(_MSC_VER) && !defined(__clang__) # define _LIBCPP_MSVC // Using Microsoft Visual C++ compiler # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) # define _LIBCPP_WARNING(x) __pragma(message(__FILE__ "(" _LIBCPP_TOSTRING(__LINE__) ") : warning note: " x)) # endif # // If mingw not explicitly detected, assume using MS C runtime only. # ifndef __MINGW32__ # define _LIBCPP_MSVCRT // Using Microsoft's C Runtime library # endif #endif // _WIN32 #ifdef __sun__ # include # ifdef _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 1 # define _LIBCPP_BIG_ENDIAN 0 # else # define _LIBCPP_LITTLE_ENDIAN 0 # define _LIBCPP_BIG_ENDIAN 1 # endif #endif // __sun__ #if defined(__CloudABI__) // Certain architectures provide arc4random(). Prefer using // arc4random() over /dev/{u,}random to make it possible to obtain // random data even when using sandboxing mechanisms such as chroots, // Capsicum, etc. # define _LIBCPP_USING_ARC4_RANDOM #elif defined(__native_client__) // NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, // including accesses to the special files under /dev. C++11's // std::random_device is instead exposed through a NaCl syscall. # define _LIBCPP_USING_NACL_RANDOM #elif defined(_WIN32) # define _LIBCPP_USING_WIN32_RANDOM #else # define _LIBCPP_USING_DEV_RANDOM #endif #if !defined(_LIBCPP_LITTLE_ENDIAN) || !defined(_LIBCPP_BIG_ENDIAN) # include # if __BYTE_ORDER == __LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 1 # define _LIBCPP_BIG_ENDIAN 0 # elif __BYTE_ORDER == __BIG_ENDIAN # define _LIBCPP_LITTLE_ENDIAN 0 # define _LIBCPP_BIG_ENDIAN 1 # else // __BYTE_ORDER == __BIG_ENDIAN # error unable to determine endian # endif #endif // !defined(_LIBCPP_LITTLE_ENDIAN) || !defined(_LIBCPP_BIG_ENDIAN) #ifdef _WIN32 // only really useful for a DLL #ifdef _LIBCPP_DLL // this should be a compiler builtin define ideally... # ifdef cxx_EXPORTS # define _LIBCPP_HIDDEN # define _LIBCPP_FUNC_VIS __declspec(dllexport) # define _LIBCPP_TYPE_VIS __declspec(dllexport) # else # define _LIBCPP_HIDDEN # define _LIBCPP_FUNC_VIS __declspec(dllimport) # define _LIBCPP_TYPE_VIS __declspec(dllimport) # endif #else # define _LIBCPP_HIDDEN # define _LIBCPP_FUNC_VIS # define _LIBCPP_TYPE_VIS #endif #define _LIBCPP_TYPE_VIS_ONLY #define _LIBCPP_FUNC_VIS_ONLY #ifndef _LIBCPP_INLINE_VISIBILITY # ifdef _LIBCPP_MSVC # define _LIBCPP_INLINE_VISIBILITY __forceinline # else // MinGW GCC and Clang # define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) # endif #endif #ifndef _LIBCPP_EXCEPTION_ABI #define _LIBCPP_EXCEPTION_ABI _LIBCPP_TYPE_VIS #endif #ifndef _LIBCPP_ALWAYS_INLINE # ifdef _LIBCPP_MSVC # define _LIBCPP_ALWAYS_INLINE __forceinline # endif #endif #endif // _WIN32 #ifndef _LIBCPP_HIDDEN #define _LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden"))) #endif #ifndef _LIBCPP_FUNC_VIS #define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default"))) #endif #ifndef _LIBCPP_TYPE_VIS # if __has_attribute(__type_visibility__) # define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default"))) # else # define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default"))) # endif #endif #ifndef _LIBCPP_TYPE_VIS_ONLY # define _LIBCPP_TYPE_VIS_ONLY _LIBCPP_TYPE_VIS #endif #ifndef _LIBCPP_FUNC_VIS_ONLY # define _LIBCPP_FUNC_VIS_ONLY _LIBCPP_FUNC_VIS #endif #ifndef _LIBCPP_INLINE_VISIBILITY #define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__)) #endif #ifndef _LIBCPP_EXCEPTION_ABI #define _LIBCPP_EXCEPTION_ABI __attribute__ ((__visibility__("default"))) #endif #ifndef _LIBCPP_ALWAYS_INLINE #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__)) #endif #if defined(__clang__) // _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT left here for backward compatibility. #if (defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && \ !defined(__arm__)) || \ defined(_LIBCPP_ALTERNATE_STRING_LAYOUT) #define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT #endif #if __has_feature(cxx_alignas) # define _ALIGNAS_TYPE(x) alignas(x) # define _ALIGNAS(x) alignas(x) #else # define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) # define _ALIGNAS(x) __attribute__((__aligned__(x))) #endif #if !__has_feature(cxx_alias_templates) #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #endif #if __cplusplus < 201103L typedef __char16_t char16_t; typedef __char32_t char32_t; #endif #if !(__has_feature(cxx_exceptions)) #define _LIBCPP_NO_EXCEPTIONS #endif #if !(__has_feature(cxx_rtti)) #define _LIBCPP_NO_RTTI #endif #if !(__has_feature(cxx_strong_enums)) #define _LIBCPP_HAS_NO_STRONG_ENUMS #endif #if !(__has_feature(cxx_decltype)) #define _LIBCPP_HAS_NO_DECLTYPE #endif #if __has_feature(cxx_attributes) # define _LIBCPP_NORETURN [[noreturn]] #else # define _LIBCPP_NORETURN __attribute__ ((noreturn)) #endif #define _LIBCPP_UNUSED __attribute__((__unused__)) #if !(__has_feature(cxx_default_function_template_args)) #define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #endif #if !(__has_feature(cxx_defaulted_functions)) #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #endif // !(__has_feature(cxx_defaulted_functions)) #if !(__has_feature(cxx_deleted_functions)) #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #endif // !(__has_feature(cxx_deleted_functions)) #if !(__has_feature(cxx_lambdas)) #define _LIBCPP_HAS_NO_LAMBDAS #endif #if !(__has_feature(cxx_nullptr)) #define _LIBCPP_HAS_NO_NULLPTR #endif #if !(__has_feature(cxx_rvalue_references)) #define _LIBCPP_HAS_NO_RVALUE_REFERENCES #endif #if !(__has_feature(cxx_static_assert)) #define _LIBCPP_HAS_NO_STATIC_ASSERT #endif #if !(__has_feature(cxx_auto_type)) #define _LIBCPP_HAS_NO_AUTO_TYPE #endif #if !(__has_feature(cxx_access_control_sfinae)) || !__has_feature(cxx_trailing_return) #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #endif #if !(__has_feature(cxx_variadic_templates)) #define _LIBCPP_HAS_NO_VARIADICS #endif #if !(__has_feature(cxx_trailing_return)) #define _LIBCPP_HAS_NO_TRAILING_RETURN #endif #if !(__has_feature(cxx_generalized_initializers)) #define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #endif #if __has_feature(is_base_of) # define _LIBCPP_HAS_IS_BASE_OF #endif #if __has_feature(is_final) # define _LIBCPP_HAS_IS_FINAL #endif // Objective-C++ features (opt-in) #if __has_feature(objc_arc) #define _LIBCPP_HAS_OBJC_ARC #endif #if __has_feature(objc_arc_weak) #define _LIBCPP_HAS_OBJC_ARC_WEAK #define _LIBCPP_HAS_NO_STRONG_ENUMS #endif #if !(__has_feature(cxx_constexpr)) #define _LIBCPP_HAS_NO_CONSTEXPR #endif #if !(__has_feature(cxx_relaxed_constexpr)) #define _LIBCPP_HAS_NO_CXX14_CONSTEXPR #endif #if !(__has_feature(cxx_variable_templates)) #define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #endif #if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L #if defined(__FreeBSD__) #define _LIBCPP_HAS_QUICK_EXIT #define _LIBCPP_HAS_C11_FEATURES #elif defined(__ANDROID__) #define _LIBCPP_HAS_QUICK_EXIT #elif defined(__linux__) #if !defined(_LIBCPP_HAS_MUSL_LIBC) # include #if __GLIBC_PREREQ(2, 15) #define _LIBCPP_HAS_QUICK_EXIT #endif #if __GLIBC_PREREQ(2, 17) #define _LIBCPP_HAS_C11_FEATURES #endif #else // defined(_LIBCPP_HAS_MUSL_LIBC) #define _LIBCPP_HAS_QUICK_EXIT #define _LIBCPP_HAS_C11_FEATURES #endif #endif // __linux__ #endif #if !(__has_feature(cxx_noexcept)) #define _LIBCPP_HAS_NO_NOEXCEPT #endif #if __has_feature(underlying_type) # define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) #endif #if __has_feature(is_literal) # define _LIBCPP_IS_LITERAL(T) __is_literal(T) #endif // Inline namespaces are available in Clang regardless of C++ dialect. #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE { #define _LIBCPP_END_NAMESPACE_STD } } #define _VSTD std::_LIBCPP_NAMESPACE namespace std { inline namespace _LIBCPP_NAMESPACE { } } #if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer) #define _LIBCPP_HAS_NO_ASAN #endif #elif defined(__GNUC__) #define _ALIGNAS(x) __attribute__((__aligned__(x))) #define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) #define _LIBCPP_NORETURN __attribute__((noreturn)) #define _LIBCPP_UNUSED __attribute__((__unused__)) #if _GNUC_VER >= 407 #define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) #define _LIBCPP_IS_LITERAL(T) __is_literal_type(T) #define _LIBCPP_HAS_IS_FINAL #endif #if defined(__GNUC__) && _GNUC_VER >= 403 # define _LIBCPP_HAS_IS_BASE_OF #endif #if !__EXCEPTIONS #define _LIBCPP_NO_EXCEPTIONS #endif #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES // constexpr was added to GCC in 4.6. #if _GNUC_VER < 406 #define _LIBCPP_HAS_NO_CONSTEXPR // Can only use constexpr in c++11 mode. #elif !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L #define _LIBCPP_HAS_NO_CONSTEXPR #endif // Determine if GCC supports relaxed constexpr #if !defined(__cpp_constexpr) || __cpp_constexpr < 201304L #define _LIBCPP_HAS_NO_CXX14_CONSTEXPR #endif // GCC 5 will support variable templates #if !defined(__cpp_variable_templates) || __cpp_variable_templates < 201304L #define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #endif #ifndef __GXX_EXPERIMENTAL_CXX0X__ #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #define _LIBCPP_HAS_NO_DECLTYPE #define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #define _LIBCPP_HAS_NO_NULLPTR #define _LIBCPP_HAS_NO_STATIC_ASSERT #define _LIBCPP_HAS_NO_UNICODE_CHARS #define _LIBCPP_HAS_NO_VARIADICS #define _LIBCPP_HAS_NO_RVALUE_REFERENCES #define _LIBCPP_HAS_NO_STRONG_ENUMS #define _LIBCPP_HAS_NO_NOEXCEPT #else // __GXX_EXPERIMENTAL_CXX0X__ #if _GNUC_VER < 403 #define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_RVALUE_REFERENCES #define _LIBCPP_HAS_NO_STATIC_ASSERT #endif #if _GNUC_VER < 404 #define _LIBCPP_HAS_NO_DECLTYPE #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #define _LIBCPP_HAS_NO_TRAILING_RETURN #define _LIBCPP_HAS_NO_UNICODE_CHARS #define _LIBCPP_HAS_NO_VARIADICS #define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #endif // _GNUC_VER < 404 #if _GNUC_VER < 406 #define _LIBCPP_HAS_NO_NOEXCEPT #define _LIBCPP_HAS_NO_NULLPTR #endif #if _GNUC_VER < 407 #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #endif #endif // __GXX_EXPERIMENTAL_CXX0X__ #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { namespace _LIBCPP_NAMESPACE { #define _LIBCPP_END_NAMESPACE_STD } } #define _VSTD std::_LIBCPP_NAMESPACE namespace std { namespace _LIBCPP_NAMESPACE { } using namespace _LIBCPP_NAMESPACE __attribute__((__strong__)); } #if !defined(_LIBCPP_HAS_NO_ASAN) && !defined(__SANITIZE_ADDRESS__) #define _LIBCPP_HAS_NO_ASAN #endif #elif defined(_LIBCPP_MSVC) #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #define _LIBCPP_HAS_NO_CONSTEXPR #define _LIBCPP_HAS_NO_CXX14_CONSTEXPR #define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #define _LIBCPP_HAS_NO_UNICODE_CHARS #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #define _LIBCPP_HAS_NO_NOEXCEPT #define __alignof__ __alignof #define _LIBCPP_NORETURN __declspec(noreturn) #define _LIBCPP_UNUSED #define _ALIGNAS(x) __declspec(align(x)) #define _LIBCPP_HAS_NO_VARIADICS #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { #define _LIBCPP_END_NAMESPACE_STD } #define _VSTD std # define _LIBCPP_WEAK namespace std { } #define _LIBCPP_HAS_NO_ASAN #elif defined(__IBMCPP__) #define _ALIGNAS(x) __attribute__((__aligned__(x))) #define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) #define _ATTRIBUTE(x) __attribute__((x)) #define _LIBCPP_NORETURN __attribute__((noreturn)) #define _LIBCPP_UNUSED #define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #define _LIBCPP_HAS_NO_ADVANCED_SFINAE #define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #define _LIBCPP_HAS_NO_NOEXCEPT #define _LIBCPP_HAS_NO_NULLPTR #define _LIBCPP_HAS_NO_UNICODE_CHARS #define _LIBCPP_HAS_IS_BASE_OF #define _LIBCPP_HAS_IS_FINAL #define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES #if defined(_AIX) #define __MULTILOCALE_API #endif #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE { #define _LIBCPP_END_NAMESPACE_STD } } #define _VSTD std::_LIBCPP_NAMESPACE namespace std { inline namespace _LIBCPP_NAMESPACE { } } #define _LIBCPP_HAS_NO_ASAN #endif // __clang__ || __GNUC__ || _MSC_VER || __IBMCPP__ #ifndef _LIBCPP_HAS_NO_NOEXCEPT # define _NOEXCEPT noexcept # define _NOEXCEPT_(x) noexcept(x) #else # define _NOEXCEPT throw() # define _NOEXCEPT_(x) #endif #ifdef _LIBCPP_HAS_NO_UNICODE_CHARS typedef unsigned short char16_t; typedef unsigned int char32_t; #endif // _LIBCPP_HAS_NO_UNICODE_CHARS #ifndef __SIZEOF_INT128__ #define _LIBCPP_HAS_NO_INT128 #endif #ifdef _LIBCPP_HAS_NO_STATIC_ASSERT extern "C++" { template struct __static_assert_test; template <> struct __static_assert_test {}; template struct __static_assert_check {}; } #define static_assert(__b, __m) \ typedef __static_assert_check)> \ _LIBCPP_CONCAT(__t, __LINE__) #endif // _LIBCPP_HAS_NO_STATIC_ASSERT #ifdef _LIBCPP_HAS_NO_DECLTYPE // GCC 4.6 provides __decltype in all standard modes. #if !__is_identifier(__decltype) || _GNUC_VER >= 406 # define decltype(__x) __decltype(__x) #else # define decltype(__x) __typeof__(__x) #endif #endif #ifdef _LIBCPP_HAS_NO_CONSTEXPR #define _LIBCPP_CONSTEXPR #else #define _LIBCPP_CONSTEXPR constexpr #endif #ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS #define _LIBCPP_DEFAULT {} #else #define _LIBCPP_DEFAULT = default; #endif #ifdef __GNUC__ #define _NOALIAS __attribute__((__malloc__)) #else #define _NOALIAS #endif #if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) # define _LIBCPP_EXPLICIT explicit #else # define _LIBCPP_EXPLICIT #endif #if !__has_builtin(__builtin_operator_new) || !__has_builtin(__builtin_operator_delete) # define _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE #endif #ifdef _LIBCPP_HAS_NO_STRONG_ENUMS #define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_TYPE_VIS x { enum __lx #define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ __lx __v_; \ _LIBCPP_ALWAYS_INLINE x(__lx __v) : __v_(__v) {} \ _LIBCPP_ALWAYS_INLINE explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \ }; #else // _LIBCPP_HAS_NO_STRONG_ENUMS #define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_TYPE_VIS x #define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) #endif // _LIBCPP_HAS_NO_STRONG_ENUMS #ifdef _LIBCPP_DEBUG # if _LIBCPP_DEBUG == 0 # define _LIBCPP_DEBUG_LEVEL 1 # elif _LIBCPP_DEBUG == 1 # define _LIBCPP_DEBUG_LEVEL 2 # else # error Supported values for _LIBCPP_DEBUG are 0 and 1 # endif # define _LIBCPP_EXTERN_TEMPLATE(...) #endif #ifndef _LIBCPP_EXTERN_TEMPLATE #define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; #endif #ifndef _LIBCPP_EXTERN_TEMPLATE2 #define _LIBCPP_EXTERN_TEMPLATE2(...) extern template __VA_ARGS__; #endif #if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__) #define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63) #endif #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || \ defined(__sun__) || defined(__NetBSD__) || defined(__CloudABI__) #define _LIBCPP_LOCALE__L_EXTENSIONS 1 #endif #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(_NEWLIB_VERSION) && \ !defined(__CloudABI__) #define _LIBCPP_HAS_CATOPEN 1 #endif #ifdef __FreeBSD__ #define _DECLARE_C99_LDBL_MATH 1 #endif #if defined(__APPLE__) || defined(__FreeBSD__) #define _LIBCPP_HAS_DEFAULTRUNELOCALE #endif #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) #define _LIBCPP_WCTYPE_IS_MASK #endif #ifndef _LIBCPP_TRIVIAL_PAIR_COPY_CTOR # define _LIBCPP_TRIVIAL_PAIR_COPY_CTOR 1 #endif #ifndef _LIBCPP_STD_VER # if __cplusplus <= 201103L # define _LIBCPP_STD_VER 11 # elif __cplusplus <= 201402L # define _LIBCPP_STD_VER 14 # else # define _LIBCPP_STD_VER 15 // current year, or date of c++17 ratification # endif #endif // _LIBCPP_STD_VER #if _LIBCPP_STD_VER > 11 #define _LIBCPP_DEPRECATED [[deprecated]] #else #define _LIBCPP_DEPRECATED #endif #if _LIBCPP_STD_VER <= 11 #define _LIBCPP_EXPLICIT_AFTER_CXX11 #define _LIBCPP_DEPRECATED_AFTER_CXX11 #else #define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit #define _LIBCPP_DEPRECATED_AFTER_CXX11 [[deprecated]] #endif #if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) #define _LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr #else #define _LIBCPP_CONSTEXPR_AFTER_CXX11 #endif #ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES # define _LIBCPP_EXPLICIT_MOVE(x) _VSTD::move(x) #else # define _LIBCPP_EXPLICIT_MOVE(x) (x) #endif #ifndef _LIBCPP_HAS_NO_ASAN extern "C" void __sanitizer_annotate_contiguous_container( const void *, const void *, const void *, const void *); #endif // Try to find out if RTTI is disabled. // g++ and cl.exe have RTTI on by default and define a macro when it is. // g++ only defines the macro in 4.3.2 and onwards. #if !defined(_LIBCPP_NO_RTTI) # if defined(__GNUC__) && ((__GNUC__ >= 5) || (__GNUC__ == 4 && \ (__GNUC_MINOR__ >= 3 || __GNUC_PATCHLEVEL__ >= 2))) && !defined(__GXX_RTTI) # define _LIBCPP_NO_RTTI # elif (defined(_MSC_VER) && !defined(__clang__)) && !defined(_CPPRTTI) # define _LIBCPP_NO_RTTI # endif #endif #ifndef _LIBCPP_WEAK # define _LIBCPP_WEAK __attribute__((__weak__)) #endif #if defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(_LIBCPP_HAS_NO_THREADS) # error _LIBCPP_HAS_NO_MONOTONIC_CLOCK may only be defined when \ _LIBCPP_HAS_NO_THREADS is defined. #endif // Systems that use capability-based security (FreeBSD with Capsicum, // Nuxi CloudABI) may only provide local filesystem access (using *at()). // Functions like open(), rename(), unlink() and stat() should not be // used, as they attempt to access the global filesystem namespace. #ifdef __CloudABI__ #define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE #endif // CloudABI is intended for running networked services. Processes do not // have standard input and output channels. #ifdef __CloudABI__ #define _LIBCPP_HAS_NO_STDIN #define _LIBCPP_HAS_NO_STDOUT #endif #if defined(__ANDROID__) || defined(__CloudABI__) || defined(_LIBCPP_HAS_MUSL_LIBC) #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE #endif // Thread-unsafe functions such as strtok(), mbtowc() and localtime() // are not available. #ifdef __CloudABI__ #define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS #endif #if __has_feature(cxx_atomic) || __has_extension(c_atomic) #define _LIBCPP_HAS_C_ATOMIC_IMP #elif _GNUC_VER > 407 #define _LIBCPP_HAS_GCC_ATOMIC_IMP #endif #if (!defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)) \ || defined(_LIBCPP_HAS_NO_THREADS) #define _LIBCPP_HAS_NO_ATOMIC_HEADER #endif #endif // __cplusplus #endif // _LIBCPP_CONFIG diff --git a/include/__hash_table b/include/__hash_table index cfa763ab217a..c7d1ef3d082f 100644 --- a/include/__hash_table +++ b/include/__hash_table @@ -1,2463 +1,2421 @@ // -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP__HASH_TABLE #define _LIBCPP__HASH_TABLE #include <__config> #include #include #include #include #include #include <__undef_min_max> #include <__undef___deallocate> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_FUNC_VIS size_t __next_prime(size_t __n); template struct __hash_node_base { typedef __hash_node_base __first_node; _NodePtr __next_; _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {} }; template struct __hash_node : public __hash_node_base < - typename pointer_traits<_VoidPtr>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__hash_node<_Tp, _VoidPtr> > -#else - rebind<__hash_node<_Tp, _VoidPtr> >::other -#endif + typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type > { typedef _Tp value_type; size_t __hash_; value_type __value_; }; inline _LIBCPP_INLINE_VISIBILITY bool __is_hash_power2(size_t __bc) { return __bc > 2 && !(__bc & (__bc - 1)); } inline _LIBCPP_INLINE_VISIBILITY size_t __constrain_hash(size_t __h, size_t __bc) { return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc; } inline _LIBCPP_INLINE_VISIBILITY size_t __next_hash_pow2(size_t __n) { return size_t(1) << (std::numeric_limits::digits - __clz(__n-1)); } template class __hash_table; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_iterator { typedef _NodePtr __node_pointer; __node_pointer __node_; public: typedef forward_iterator_tag iterator_category; typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type; typedef typename pointer_traits<__node_pointer>::difference_type difference_type; typedef value_type& reference; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __node_(nullptr) #endif { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_iterator(const __hash_iterator& __i) : __node_(__i.__node_) { __get_db()->__iterator_copy(this, &__i); } _LIBCPP_INLINE_VISIBILITY ~__hash_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator=(const __hash_iterator& __i) { if (this != &__i) { __get_db()->__iterator_copy(this, &__i); __node_ = __i.__node_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container iterator"); #endif return __node_->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container iterator"); #endif return pointer_traits::pointer_to(__node_->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable unordered container iterator"); #endif __node_ = __node_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __hash_iterator operator++(int) { __hash_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) { return __x.__node_ == __y.__node_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) {return !(__x == __y);} private: #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_iterator(__node_pointer __node, const void* __c) _NOEXCEPT : __node_(__node) { __get_db()->__insert_ic(this, __c); } #else _LIBCPP_INLINE_VISIBILITY __hash_iterator(__node_pointer __node) _NOEXCEPT : __node_(__node) {} #endif template friend class __hash_table; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; }; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator { typedef _ConstNodePtr __node_pointer; __node_pointer __node_; typedef typename remove_const< typename pointer_traits<__node_pointer>::element_type >::type __node; public: typedef forward_iterator_tag iterator_category; typedef typename __node::value_type value_type; typedef typename pointer_traits<__node_pointer>::difference_type difference_type; typedef const value_type& reference; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__node> -#else - rebind<__node>::other -#endif - __non_const_node_pointer; + typedef typename __rebind_pointer<__node_pointer, const value_type>::type pointer; + typedef typename __rebind_pointer<__node_pointer, __node>::type __non_const_node_pointer; typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator; _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __node_(nullptr) #endif { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__iterator_copy(this, &__x); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(const __hash_const_iterator& __i) : __node_(__i.__node_) { __get_db()->__iterator_copy(this, &__i); } _LIBCPP_INLINE_VISIBILITY ~__hash_const_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator=(const __hash_const_iterator& __i) { if (this != &__i) { __get_db()->__iterator_copy(this, &__i); __node_ = __i.__node_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container const_iterator"); #endif return __node_->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container const_iterator"); #endif return pointer_traits::pointer_to(__node_->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable unordered container const_iterator"); #endif __node_ = __node_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator operator++(int) { __hash_const_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) { return __x.__node_ == __y.__node_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {return !(__x == __y);} private: #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(__node_pointer __node, const void* __c) _NOEXCEPT : __node_(__node) { __get_db()->__insert_ic(this, __c); } #else _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(__node_pointer __node) _NOEXCEPT : __node_(__node) {} #endif template friend class __hash_table; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; }; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator { typedef _NodePtr __node_pointer; __node_pointer __node_; size_t __bucket_; size_t __bucket_count_; typedef pointer_traits<__node_pointer> __pointer_traits; public: typedef forward_iterator_tag iterator_category; typedef typename __pointer_traits::element_type::value_type value_type; typedef typename __pointer_traits::difference_type difference_type; typedef value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator(const __hash_local_iterator& __i) : __node_(__i.__node_), __bucket_(__i.__bucket_), __bucket_count_(__i.__bucket_count_) { __get_db()->__iterator_copy(this, &__i); } _LIBCPP_INLINE_VISIBILITY ~__hash_local_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator=(const __hash_local_iterator& __i) { if (this != &__i) { __get_db()->__iterator_copy(this, &__i); __node_ = __i.__node_; __bucket_ = __i.__bucket_; __bucket_count_ = __i.__bucket_count_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container local_iterator"); #endif return __node_->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container local_iterator"); #endif return pointer_traits::pointer_to(__node_->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable unordered container local_iterator"); #endif __node_ = __node_->__next_; if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) __node_ = nullptr; return *this; } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator operator++(int) { __hash_local_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) { return __x.__node_ == __y.__node_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {return !(__x == __y);} private: #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator(__node_pointer __node, size_t __bucket, size_t __bucket_count, const void* __c) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { __get_db()->__insert_ic(this, __c); if (__node_ != nullptr) __node_ = __node_->__next_; } #else _LIBCPP_INLINE_VISIBILITY __hash_local_iterator(__node_pointer __node, size_t __bucket, size_t __bucket_count) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { if (__node_ != nullptr) __node_ = __node_->__next_; } #endif template friend class __hash_table; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; }; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator { typedef _ConstNodePtr __node_pointer; __node_pointer __node_; size_t __bucket_; size_t __bucket_count_; typedef pointer_traits<__node_pointer> __pointer_traits; typedef typename __pointer_traits::element_type __node; typedef typename remove_const<__node>::type __non_const_node; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__non_const_node> -#else - rebind<__non_const_node>::other -#endif - __non_const_node_pointer; + typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type + __non_const_node_pointer; + typedef __hash_local_iterator<__non_const_node_pointer> __non_const_iterator; public: typedef forward_iterator_tag iterator_category; typedef typename remove_const< typename __pointer_traits::element_type::value_type >::type value_type; typedef typename __pointer_traits::difference_type difference_type; typedef const value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, const value_type>::type + pointer; + _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_), __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__iterator_copy(this, &__x); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(const __hash_const_local_iterator& __i) : __node_(__i.__node_), __bucket_(__i.__bucket_), __bucket_count_(__i.__bucket_count_) { __get_db()->__iterator_copy(this, &__i); } _LIBCPP_INLINE_VISIBILITY ~__hash_const_local_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) { if (this != &__i) { __get_db()->__iterator_copy(this, &__i); __node_ = __i.__node_; __bucket_ = __i.__bucket_; __bucket_count_ = __i.__bucket_count_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); #endif return __node_->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); #endif return pointer_traits::pointer_to(__node_->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable unordered container const_local_iterator"); #endif __node_ = __node_->__next_; if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) __node_ = nullptr; return *this; } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator operator++(int) { __hash_const_local_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) { return __x.__node_ == __y.__node_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {return !(__x == __y);} private: #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(__node_pointer __node, size_t __bucket, size_t __bucket_count, const void* __c) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { __get_db()->__insert_ic(this, __c); if (__node_ != nullptr) __node_ = __node_->__next_; } #else _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator(__node_pointer __node, size_t __bucket, size_t __bucket_count) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { if (__node_ != nullptr) __node_ = __node_->__next_; } #endif template friend class __hash_table; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; }; template class __bucket_list_deallocator { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::size_type size_type; __compressed_pair __data_; public: typedef typename __alloc_traits::pointer pointer; _LIBCPP_INLINE_VISIBILITY __bucket_list_deallocator() _NOEXCEPT_(is_nothrow_default_constructible::value) : __data_(0) {} _LIBCPP_INLINE_VISIBILITY __bucket_list_deallocator(const allocator_type& __a, size_type __size) _NOEXCEPT_(is_nothrow_copy_constructible::value) : __data_(__size, __a) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __bucket_list_deallocator(__bucket_list_deallocator&& __x) _NOEXCEPT_(is_nothrow_move_constructible::value) : __data_(_VSTD::move(__x.__data_)) { __x.size() = 0; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY size_type& size() _NOEXCEPT {return __data_.first();} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __data_.first();} _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() _NOEXCEPT {return __data_.second();} _LIBCPP_INLINE_VISIBILITY const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();} _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { __alloc_traits::deallocate(__alloc(), __p, size()); } }; template class __hash_map_node_destructor; template class __hash_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: allocator_type& __na_; __hash_node_destructor& operator=(const __hash_node_destructor&); public: bool __value_constructed; _LIBCPP_INLINE_VISIBILITY explicit __hash_node_destructor(allocator_type& __na, bool __constructed = false) _NOEXCEPT : __na_(__na), __value_constructed(__constructed) {} _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } template friend class __hash_map_node_destructor; }; template class __hash_table { public: typedef _Tp value_type; typedef _Hash hasher; typedef _Equal key_equal; typedef _Alloc allocator_type; private: typedef allocator_traits __alloc_traits; public: typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; public: // Create __node typedef __hash_node __node; typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; typedef allocator_traits<__node_allocator> __node_traits; typedef typename __node_traits::pointer __node_pointer; typedef typename __node_traits::pointer __node_const_pointer; typedef __hash_node_base<__node_pointer> __first_node; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__first_node> -#else - rebind<__first_node>::other -#endif - __node_base_pointer; + typedef typename __rebind_pointer<__node_pointer, __first_node>::type + __node_base_pointer; private: typedef typename __rebind_alloc_helper<__node_traits, __node_pointer>::type __pointer_allocator; typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter; typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list; typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits; typedef typename __bucket_list_deleter::pointer __node_pointer_pointer; // --- Member data begin --- __bucket_list __bucket_list_; __compressed_pair<__first_node, __node_allocator> __p1_; __compressed_pair __p2_; __compressed_pair __p3_; // --- Member data end --- _LIBCPP_INLINE_VISIBILITY size_type& size() _NOEXCEPT {return __p2_.first();} public: _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __p2_.first();} _LIBCPP_INLINE_VISIBILITY hasher& hash_function() _NOEXCEPT {return __p2_.second();} _LIBCPP_INLINE_VISIBILITY const hasher& hash_function() const _NOEXCEPT {return __p2_.second();} _LIBCPP_INLINE_VISIBILITY float& max_load_factor() _NOEXCEPT {return __p3_.first();} _LIBCPP_INLINE_VISIBILITY float max_load_factor() const _NOEXCEPT {return __p3_.first();} _LIBCPP_INLINE_VISIBILITY key_equal& key_eq() _NOEXCEPT {return __p3_.second();} _LIBCPP_INLINE_VISIBILITY const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();} _LIBCPP_INLINE_VISIBILITY __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();} _LIBCPP_INLINE_VISIBILITY const __node_allocator& __node_alloc() const _NOEXCEPT {return __p1_.second();} public: typedef __hash_iterator<__node_pointer> iterator; typedef __hash_const_iterator<__node_pointer> const_iterator; typedef __hash_local_iterator<__node_pointer> local_iterator; typedef __hash_const_local_iterator<__node_pointer> const_local_iterator; _LIBCPP_INLINE_VISIBILITY __hash_table() _NOEXCEPT_( is_nothrow_default_constructible<__bucket_list>::value && is_nothrow_default_constructible<__first_node>::value && is_nothrow_default_constructible<__node_allocator>::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value); _LIBCPP_INLINE_VISIBILITY __hash_table(const hasher& __hf, const key_equal& __eql); __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a); explicit __hash_table(const allocator_type& __a); __hash_table(const __hash_table& __u); __hash_table(const __hash_table& __u, const allocator_type& __a); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __hash_table(__hash_table&& __u) _NOEXCEPT_( is_nothrow_move_constructible<__bucket_list>::value && is_nothrow_move_constructible<__first_node>::value && is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); __hash_table(__hash_table&& __u, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES ~__hash_table(); __hash_table& operator=(const __hash_table& __u); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __hash_table& operator=(__hash_table&& __u) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); #endif template void __assign_unique(_InputIterator __first, _InputIterator __last); template void __assign_multi(_InputIterator __first, _InputIterator __last); _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT { return allocator_traits<__pointer_allocator>::max_size( __bucket_list_.get_deleter().__alloc()); } pair __node_insert_unique(__node_pointer __nd); iterator __node_insert_multi(__node_pointer __nd); iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template pair __emplace_unique(_Args&&... __args); template iterator __emplace_multi(_Args&&... __args); template iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template _LIBCPP_INLINE_VISIBILITY pair __insert_unique_value(_ValueTp&& __x); #else _LIBCPP_INLINE_VISIBILITY pair __insert_unique_value(const value_type& __x); #endif pair __insert_unique(const value_type& __x); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES pair __insert_unique(value_type&& __x); template pair __insert_unique(_Pp&& __x); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template iterator __insert_multi(_Pp&& __x); template iterator __insert_multi(const_iterator __p, _Pp&& __x); #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES iterator __insert_multi(const value_type& __x); iterator __insert_multi(const_iterator __p, const value_type& __x); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void clear() _NOEXCEPT; void rehash(size_type __n); _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {rehash(static_cast(ceil(__n / max_load_factor())));} _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT { return __bucket_list_.get_deleter().size(); } _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY size_type bucket(const _Key& __k) const { _LIBCPP_ASSERT(bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0"); return __constrain_hash(hash_function()(__k), bucket_count()); } template iterator find(const _Key& __x); template const_iterator find(const _Key& __x) const; typedef __hash_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; iterator erase(const_iterator __p); iterator erase(const_iterator __first, const_iterator __last); template size_type __erase_unique(const _Key& __k); template size_type __erase_multi(const _Key& __k); __node_holder remove(const_iterator __p) _NOEXCEPT; template _LIBCPP_INLINE_VISIBILITY size_type __count_unique(const _Key& __k) const; template size_type __count_multi(const _Key& __k) const; template pair __equal_range_unique(const _Key& __k); template pair __equal_range_unique(const _Key& __k) const; template pair __equal_range_multi(const _Key& __k); template pair __equal_range_multi(const _Key& __k) const; void swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_( __is_nothrow_swappable::value && __is_nothrow_swappable::value && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || __is_nothrow_swappable<__pointer_allocator>::value) && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) ); #else _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value); #endif _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());} size_type bucket_size(size_type __n) const; _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT { size_type __bc = bucket_count(); return __bc != 0 ? (float)size() / __bc : 0.f; } _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT { _LIBCPP_ASSERT(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0"); max_load_factor() = _VSTD::max(__mlf, load_factor()); } _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n) { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()"); #if _LIBCPP_DEBUG_LEVEL >= 2 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); #else return local_iterator(__bucket_list_[__n], __n, bucket_count()); #endif } _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n) { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()"); #if _LIBCPP_DEBUG_LEVEL >= 2 return local_iterator(nullptr, __n, bucket_count(), this); #else return local_iterator(nullptr, __n, bucket_count()); #endif } _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()"); #if _LIBCPP_DEBUG_LEVEL >= 2 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); #else return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); #endif } _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()"); #if _LIBCPP_DEBUG_LEVEL >= 2 return const_local_iterator(nullptr, __n, bucket_count(), this); #else return const_local_iterator(nullptr, __n, bucket_count()); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 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_DEBUG_LEVEL >= 2 private: void __rehash(size_type __n); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template __node_holder __construct_node(_Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS __node_holder __construct_node(value_type&& __v, size_t __hash); #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node(const value_type& __v); #endif __node_holder __construct_node(const value_type& __v, size_t __hash); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table& __u) {__copy_assign_alloc(__u, integral_constant());} void __copy_assign_alloc(const __hash_table& __u, true_type); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table&, false_type) {} void __move_assign(__hash_table& __u, false_type); void __move_assign(__hash_table& __u, true_type) _NOEXCEPT_( is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table& __u) _NOEXCEPT_( !__node_traits::propagate_on_container_move_assignment::value || (is_nothrow_move_assignable<__pointer_allocator>::value && is_nothrow_move_assignable<__node_allocator>::value)) {__move_assign_alloc(__u, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table& __u, true_type) _NOEXCEPT_( is_nothrow_move_assignable<__pointer_allocator>::value && is_nothrow_move_assignable<__node_allocator>::value) { __bucket_list_.get_deleter().__alloc() = _VSTD::move(__u.__bucket_list_.get_deleter().__alloc()); __node_alloc() = _VSTD::move(__u.__node_alloc()); } _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} void __deallocate(__node_pointer __np) _NOEXCEPT; __node_pointer __detach() _NOEXCEPT; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; }; template inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() _NOEXCEPT_( is_nothrow_default_constructible<__bucket_list>::value && is_nothrow_default_constructible<__first_node>::value && is_nothrow_default_constructible<__node_allocator>::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value) : __p2_(0), __p3_(1.0f) { } template inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql) : __bucket_list_(nullptr, __bucket_list_deleter()), __p1_(), __p2_(0, __hf), __p3_(1.0f, __eql) { } template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), __p1_(__node_allocator(__a)), __p2_(0, __hf), __p3_(1.0f, __eql) { } template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a) : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), __p1_(__node_allocator(__a)), __p2_(0), __p3_(1.0f) { } template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u) : __bucket_list_(nullptr, __bucket_list_deleter(allocator_traits<__pointer_allocator>:: select_on_container_copy_construction( __u.__bucket_list_.get_deleter().__alloc()), 0)), __p1_(allocator_traits<__node_allocator>:: select_on_container_copy_construction(__u.__node_alloc())), __p2_(0, __u.hash_function()), __p3_(__u.__p3_) { } template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, const allocator_type& __a) : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), __p1_(__node_allocator(__a)), __p2_(0, __u.hash_function()), __p3_(__u.__p3_) { } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEXCEPT_( is_nothrow_move_constructible<__bucket_list>::value && is_nothrow_move_constructible<__first_node>::value && is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value) : __bucket_list_(_VSTD::move(__u.__bucket_list_)), __p1_(_VSTD::move(__u.__p1_)), __p2_(_VSTD::move(__u.__p2_)), __p3_(_VSTD::move(__u.__p3_)) { if (size() > 0) { __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } } template __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const allocator_type& __a) : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), __p1_(__node_allocator(__a)), __p2_(0, _VSTD::move(__u.hash_function())), __p3_(_VSTD::move(__u.__p3_)) { if (__a == allocator_type(__u.__node_alloc())) { __bucket_list_.reset(__u.__bucket_list_.release()); __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); __u.__bucket_list_.get_deleter().size() = 0; if (__u.size() > 0) { __p1_.first().__next_ = __u.__p1_.first().__next_; __u.__p1_.first().__next_ = nullptr; __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); size() = __u.size(); __u.size() = 0; } } } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() { __deallocate(__p1_.first().__next_); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__erase_c(this); #endif } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc( const __hash_table& __u, true_type) { if (__node_alloc() != __u.__node_alloc()) { clear(); __bucket_list_.reset(); __bucket_list_.get_deleter().size() = 0; } __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc(); __node_alloc() = __u.__node_alloc(); } template __hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) { if (this != &__u) { __copy_assign_alloc(__u); hash_function() = __u.hash_function(); key_eq() = __u.key_eq(); max_load_factor() = __u.max_load_factor(); __assign_multi(__u.begin(), __u.end()); } return *this; } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np) _NOEXCEPT { __node_allocator& __na = __node_alloc(); while (__np != nullptr) { __node_pointer __next = __np->__next_; #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__node_ == __np) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif __node_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_traits::deallocate(__na, __np, 1); __np = __next; } } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer __hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT { size_type __bc = bucket_count(); for (size_type __i = 0; __i < __bc; ++__i) __bucket_list_[__i] = nullptr; size() = 0; __node_pointer __cache = __p1_.first().__next_; __p1_.first().__next_ = nullptr; return __cache; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __hash_table& __u, true_type) _NOEXCEPT_( is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value) { clear(); __bucket_list_.reset(__u.__bucket_list_.release()); __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); __u.__bucket_list_.get_deleter().size() = 0; __move_assign_alloc(__u); size() = __u.size(); hash_function() = _VSTD::move(__u.hash_function()); max_load_factor() = __u.max_load_factor(); key_eq() = _VSTD::move(__u.key_eq()); __p1_.first().__next_ = __u.__p1_.first().__next_; if (size() > 0) { __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->swap(this, &__u); #endif } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __hash_table& __u, false_type) { if (__node_alloc() == __u.__node_alloc()) __move_assign(__u, true_type()); else { hash_function() = _VSTD::move(__u.hash_function()); key_eq() = _VSTD::move(__u.key_eq()); max_load_factor() = __u.max_load_factor(); if (bucket_count() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_); __node_pointer __next = __cache->__next_; __node_insert_multi(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __deallocate(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS __deallocate(__cache); } const_iterator __i = __u.begin(); while (__u.size() != 0) { __node_holder __h = __construct_node(_VSTD::move(__u.remove(__i++)->__value_)); __node_insert_multi(__h.get()); __h.release(); } } } template inline __hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value) { __move_assign(__u, integral_constant()); return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) { if (bucket_count() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__value_ = *__first; __node_pointer __next = __cache->__next_; __node_insert_unique(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __deallocate(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS __deallocate(__cache); } for (; __first != __last; ++__first) __insert_unique(*__first); } template template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) { if (bucket_count() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__value_ = *__first; __node_pointer __next = __cache->__next_; __node_insert_multi(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { __deallocate(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS __deallocate(__cache); } for (; __first != __last; ++__first) __insert_multi(*__first); } template inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__p1_.first().__next_, this); #else return iterator(__p1_.first().__next_); #endif } template inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(nullptr, this); #else return iterator(nullptr); #endif } template inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return const_iterator(__p1_.first().__next_, this); #else return const_iterator(__p1_.first().__next_); #endif } template inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return const_iterator(nullptr, this); #else return const_iterator(nullptr); #endif } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT { if (size() > 0) { __deallocate(__p1_.first().__next_); __p1_.first().__next_ = nullptr; size_type __bc = bucket_count(); for (size_type __i = 0; __i < __bc; ++__i) __bucket_list_[__i] = nullptr; size() = 0; } } template pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) { __nd->__hash_ = hash_function()(__nd->__value_); size_type __bc = bucket_count(); bool __inserted = false; __node_pointer __ndptr; size_t __chash; if (__bc != 0) { __chash = __constrain_hash(__nd->__hash_, __bc); __ndptr = __bucket_list_[__chash]; if (__ndptr != nullptr) { for (__ndptr = __ndptr->__next_; __ndptr != nullptr && __constrain_hash(__ndptr->__hash_, __bc) == __chash; __ndptr = __ndptr->__next_) { if (key_eq()(__ndptr->__value_, __nd->__value_)) goto __done; } } } { if (size()+1 > __bc * max_load_factor() || __bc == 0) { rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), size_type(ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); __chash = __constrain_hash(__nd->__hash_, __bc); } // insert_after __bucket_list_[__chash], or __first_node if bucket is null __node_pointer __pn = __bucket_list_[__chash]; if (__pn == nullptr) { __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); __nd->__next_ = __pn->__next_; __pn->__next_ = __nd; // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__nd->__next_ != nullptr) __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd; } else { __nd->__next_ = __pn->__next_; __pn->__next_ = __nd; } __ndptr = __nd; // increment size ++size(); __inserted = true; } __done: #if _LIBCPP_DEBUG_LEVEL >= 2 return pair(iterator(__ndptr, this), __inserted); #else return pair(iterator(__ndptr), __inserted); #endif } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) { __cp->__hash_ = hash_function()(__cp->__value_); size_type __bc = bucket_count(); if (size()+1 > __bc * max_load_factor() || __bc == 0) { rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), size_type(ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); } size_t __chash = __constrain_hash(__cp->__hash_, __bc); __node_pointer __pn = __bucket_list_[__chash]; if (__pn == nullptr) { __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); __cp->__next_ = __pn->__next_; __pn->__next_ = __cp; // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__cp->__next_ != nullptr) __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp; } else { for (bool __found = false; __pn->__next_ != nullptr && __constrain_hash(__pn->__next_->__hash_, __bc) == __chash; __pn = __pn->__next_) { // __found key_eq() action // false false loop // true true loop // false true set __found to true // true false break if (__found != (__pn->__next_->__hash_ == __cp->__hash_ && key_eq()(__pn->__next_->__value_, __cp->__value_))) { if (!__found) __found = true; else break; } } __cp->__next_ = __pn->__next_; __pn->__next_ = __cp; if (__cp->__next_ != nullptr) { size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc); if (__nhash != __chash) __bucket_list_[__nhash] = __cp; } } ++size(); #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__cp, this); #else return iterator(__cp); #endif } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( const_iterator __p, __node_pointer __cp) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered container"); #endif if (__p != end() && key_eq()(*__p, __cp->__value_)) { __node_pointer __np = __p.__node_; __cp->__hash_ = __np->__hash_; size_type __bc = bucket_count(); if (size()+1 > __bc * max_load_factor() || __bc == 0) { rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), size_type(ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); } size_t __chash = __constrain_hash(__cp->__hash_, __bc); __node_pointer __pp = __bucket_list_[__chash]; while (__pp->__next_ != __np) __pp = __pp->__next_; __cp->__next_ = __np; __pp->__next_ = __cp; ++size(); #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__cp, this); #else return iterator(__cp); #endif } return __node_insert_multi(__cp); } template pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x) { return __insert_unique_value(__x); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template template _LIBCPP_INLINE_VISIBILITY pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(_ValueTp&& __x) #else template _LIBCPP_INLINE_VISIBILITY pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(const value_type& __x) #endif { #if defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) typedef const value_type& _ValueTp; #endif size_t __hash = hash_function()(__x); size_type __bc = bucket_count(); bool __inserted = false; __node_pointer __nd; size_t __chash; if (__bc != 0) { __chash = __constrain_hash(__hash, __bc); __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && __constrain_hash(__nd->__hash_, __bc) == __chash; __nd = __nd->__next_) { if (key_eq()(__nd->__value_, __x)) goto __done; } } } { __node_holder __h = __construct_node(_VSTD::forward<_ValueTp>(__x), __hash); if (size()+1 > __bc * max_load_factor() || __bc == 0) { rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), size_type(ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); __chash = __constrain_hash(__hash, __bc); } // insert_after __bucket_list_[__chash], or __first_node if bucket is null __node_pointer __pn = __bucket_list_[__chash]; if (__pn == nullptr) { __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); __h->__next_ = __pn->__next_; __pn->__next_ = __h.get(); // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__h->__next_ != nullptr) __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get(); } else { __h->__next_ = __pn->__next_; __pn->__next_ = __h.get(); } __nd = __h.release(); // increment size ++size(); __inserted = true; } __done: #if _LIBCPP_DEBUG_LEVEL >= 2 return pair(iterator(__nd, this), __inserted); #else return pair(iterator(__nd), __inserted); #endif } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template template pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); pair __r = __node_insert_unique(__h.get()); if (__r.second) __h.release(); return __r; } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __node_insert_multi(__h.get()); __h.release(); return __r; } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( const_iterator __p, _Args&&... __args) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered container"); #endif __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); return __r; } #endif // _LIBCPP_HAS_NO_VARIADICS template pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(value_type&& __x) { return __insert_unique_value(_VSTD::move(__x)); } template template pair::iterator, bool> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x) { __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); pair __r = __node_insert_unique(__h.get()); if (__r.second) __h.release(); return __r; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x) { __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); iterator __r = __node_insert_multi(__h.get()); __h.release(); return __r; } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, _Pp&& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container::insert(const_iterator, rvalue) called with an iterator not" " referring to this unordered container"); #endif __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); return __r; } #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x) { __node_holder __h = __construct_node(__x); iterator __r = __node_insert_multi(__h.get()); __h.release(); return __r; } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, const value_type& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container::insert(const_iterator, lvalue) called with an iterator not" " referring to this unordered container"); #endif __node_holder __h = __construct_node(__x); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); return __r; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n) { if (__n == 1) __n = 2; else if (__n & (__n - 1)) __n = __next_prime(__n); size_type __bc = bucket_count(); if (__n > __bc) __rehash(__n); else if (__n < __bc) { __n = _VSTD::max ( __n, __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) : __next_prime(size_t(ceil(float(size()) / max_load_factor()))) ); if (__n < __bc) __rehash(__n); } } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__invalidate_all(this); #endif // _LIBCPP_DEBUG_LEVEL >= 2 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); __bucket_list_.get_deleter().size() = __nbc; if (__nbc > 0) { for (size_type __i = 0; __i < __nbc; ++__i) __bucket_list_[__i] = nullptr; __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))); __node_pointer __cp = __pp->__next_; if (__cp != nullptr) { size_type __chash = __constrain_hash(__cp->__hash_, __nbc); __bucket_list_[__chash] = __pp; size_type __phash = __chash; for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) { __chash = __constrain_hash(__cp->__hash_, __nbc); if (__chash == __phash) __pp = __cp; else { if (__bucket_list_[__chash] == nullptr) { __bucket_list_[__chash] = __pp; __pp = __cp; __phash = __chash; } else { __node_pointer __np = __cp; for (; __np->__next_ != nullptr && key_eq()(__cp->__value_, __np->__next_->__value_); __np = __np->__next_) ; __pp->__next_ = __np->__next_; __np->__next_ = __bucket_list_[__chash]->__next_; __bucket_list_[__chash]->__next_ = __cp; } } } } } } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); if (__bc != 0) { size_t __chash = __constrain_hash(__hash, __bc); __node_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && __constrain_hash(__nd->__hash_, __bc) == __chash; __nd = __nd->__next_) { if (key_eq()(__nd->__value_, __k)) #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__nd, this); #else return iterator(__nd); #endif } } } return end(); } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { size_t __hash = hash_function()(__k); size_type __bc = bucket_count(); if (__bc != 0) { size_t __chash = __constrain_hash(__hash, __bc); __node_const_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && __constrain_hash(__nd->__hash_, __bc) == __chash; __nd = __nd->__next_) { if (key_eq()(__nd->__value_, __k)) #if _LIBCPP_DEBUG_LEVEL >= 2 return const_iterator(__nd, this); #else return const_iterator(__nd); #endif } } } return end(); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; __h->__hash_ = hash_function()(__h->__value_); __h->__next_ = nullptr; return __h; } #endif // _LIBCPP_HAS_NO_VARIADICS template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v, size_t __hash) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v)); __h.get_deleter().__value_constructed = true; __h->__hash_ = __hash; __h->__next_ = nullptr; return __h; } #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); __h.get_deleter().__value_constructed = true; __h->__hash_ = hash_function()(__h->__value_); __h->__next_ = nullptr; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v, size_t __hash) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); __h.get_deleter().__value_constructed = true; __h->__hash_ = __hash; __h->__next_ = nullptr; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) { __node_pointer __np = __p.__node_; #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered container erase(iterator) called with an iterator not" " referring to this container"); _LIBCPP_ASSERT(__p != end(), "unordered container erase(iterator) called with a non-dereferenceable iterator"); iterator __r(__np, this); #else iterator __r(__np); #endif ++__r; remove(__p); return __r; } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, "unodered container::erase(iterator, iterator) called with an iterator not" " referring to this unodered container"); _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, "unodered container::erase(iterator, iterator) called with an iterator not" " referring to this unodered container"); #endif for (const_iterator __p = __first; __first != __last; __p = __first) { ++__first; erase(__p); } __node_pointer __np = __last.__node_; #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator (__np, this); #else return iterator (__np); #endif } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) { iterator __i = find(__k); if (__i == end()) return 0; erase(__i); return 1; } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) { size_type __r = 0; iterator __i = find(__k); if (__i != end()) { iterator __e = end(); do { erase(__i++); ++__r; } while (__i != __e && key_eq()(*__i, __k)); } return __r; } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT { // current node __node_pointer __cn = __p.__node_; size_type __bc = bucket_count(); size_t __chash = __constrain_hash(__cn->__hash_, __bc); // find previous node __node_pointer __pn = __bucket_list_[__chash]; for (; __pn->__next_ != __cn; __pn = __pn->__next_) ; // Fix up __bucket_list_ // if __pn is not in same bucket (before begin is not in same bucket) && // if __cn->__next_ is not in same bucket (nullptr is not in same bucket) if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())) || __constrain_hash(__pn->__hash_, __bc) != __chash) { if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash) __bucket_list_[__chash] = nullptr; } // if __cn->__next_ is not in same bucket (nullptr is in same bucket) if (__cn->__next_ != nullptr) { size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc); if (__nhash != __chash) __bucket_list_[__nhash] = __pn; } // remove __cn __pn->__next_ = __cn->__next_; __cn->__next_ = nullptr; --size(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__node_ == __cn) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif return __node_holder(__cn, _Dp(__node_alloc(), true)); } template template inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const { return static_cast(find(__k) != end()); } template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const { size_type __r = 0; const_iterator __i = find(__k); if (__i != end()) { const_iterator __e = end(); do { ++__i; ++__r; } while (__i != __e && key_eq()(*__i, __k)); } return __r; } template template pair::iterator, typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( const _Key& __k) { iterator __i = find(__k); iterator __j = __i; if (__i != end()) ++__j; return pair(__i, __j); } template template pair::const_iterator, typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( const _Key& __k) const { const_iterator __i = find(__k); const_iterator __j = __i; if (__i != end()) ++__j; return pair(__i, __j); } template template pair::iterator, typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( const _Key& __k) { iterator __i = find(__k); iterator __j = __i; if (__i != end()) { iterator __e = end(); do { ++__j; } while (__j != __e && key_eq()(*__j, __k)); } return pair(__i, __j); } template template pair::const_iterator, typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( const _Key& __k) const { const_iterator __i = find(__k); const_iterator __j = __i; if (__i != end()) { const_iterator __e = end(); do { ++__j; } while (__j != __e && key_eq()(*__j, __k)); } return pair(__i, __j); } template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_( __is_nothrow_swappable::value && __is_nothrow_swappable::value && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || __is_nothrow_swappable<__pointer_allocator>::value) && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) ) #else _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) #endif { { __node_pointer_pointer __npp = __bucket_list_.release(); __bucket_list_.reset(__u.__bucket_list_.release()); __u.__bucket_list_.reset(__npp); } _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size()); __swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc()); __swap_allocator(__node_alloc(), __u.__node_alloc()); _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_); __p2_.swap(__u.__p2_); __p3_.swap(__u.__p3_); if (size() > 0) __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); if (__u.size() > 0) __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first())); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->swap(this, &__u); #endif } template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const { _LIBCPP_ASSERT(__n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()"); __node_const_pointer __np = __bucket_list_[__n]; size_type __bc = bucket_count(); size_type __r = 0; if (__np != nullptr) { for (__np = __np->__next_; __np != nullptr && __constrain_hash(__np->__hash_, __bc) == __n; __np = __np->__next_, ++__r) ; } return __r; } template inline _LIBCPP_INLINE_VISIBILITY void swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } #if _LIBCPP_DEBUG_LEVEL >= 2 template bool __hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const { return __i->__node_ != nullptr; } template bool __hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const { return false; } template bool __hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const { return false; } template bool __hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const { return false; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP__HASH_TABLE diff --git a/include/__tree b/include/__tree index 6391609b3982..94565bc3f74c 100644 --- a/include/__tree +++ b/include/__tree @@ -1,2297 +1,2292 @@ // -*- C++ -*- //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP___TREE #define _LIBCPP___TREE #include <__config> #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template class __tree; template class _LIBCPP_TYPE_VIS_ONLY __tree_iterator; template class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; /* _NodePtr algorithms The algorithms taking _NodePtr are red black tree algorithms. Those algorithms taking a parameter named __root should assume that __root points to a proper red black tree (unless otherwise specified). Each algorithm herein assumes that __root->__parent_ points to a non-null structure which has a member __left_ which points back to __root. No other member is read or written to at __root->__parent_. __root->__parent_ will be referred to below (in comments only) as end_node. end_node->__left_ is an externably accessible lvalue for __root, and can be changed by node insertion and removal (without explicit reference to end_node). All nodes (with the exception of end_node), even the node referred to as __root, have a non-null __parent_ field. */ // Returns: true if __x is a left child of its parent, else false // Precondition: __x != nullptr. template inline _LIBCPP_INLINE_VISIBILITY bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { return __x == __x->__parent_->__left_; } // Determintes if the subtree rooted at __x is a proper red black subtree. If // __x is a proper subtree, returns the black height (null counts as 1). If // __x is an improper subtree, returns 0. template unsigned __tree_sub_invariant(_NodePtr __x) { if (__x == nullptr) return 1; // parent consistency checked by caller // check __x->__left_ consistency if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x) return 0; // check __x->__right_ consistency if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x) return 0; // check __x->__left_ != __x->__right_ unless both are nullptr if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr) return 0; // If this is red, neither child can be red if (!__x->__is_black_) { if (__x->__left_ && !__x->__left_->__is_black_) return 0; if (__x->__right_ && !__x->__right_->__is_black_) return 0; } unsigned __h = __tree_sub_invariant(__x->__left_); if (__h == 0) return 0; // invalid left subtree if (__h != __tree_sub_invariant(__x->__right_)) return 0; // invalid or different height right subtree return __h + __x->__is_black_; // return black height of this node } // Determintes if the red black tree rooted at __root is a proper red black tree. // __root == nullptr is a proper tree. Returns true is __root is a proper // red black tree, else returns false. template bool __tree_invariant(_NodePtr __root) { if (__root == nullptr) return true; // check __x->__parent_ consistency if (__root->__parent_ == nullptr) return false; if (!__tree_is_left_child(__root)) return false; // root must be black if (!__root->__is_black_) return false; // do normal node checks return __tree_sub_invariant(__root) != 0; } // Returns: pointer to the left-most node under __x. // Precondition: __x != nullptr. template inline _LIBCPP_INLINE_VISIBILITY _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { while (__x->__left_ != nullptr) __x = __x->__left_; return __x; } // Returns: pointer to the right-most node under __x. // Precondition: __x != nullptr. template inline _LIBCPP_INLINE_VISIBILITY _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { while (__x->__right_ != nullptr) __x = __x->__right_; return __x; } // Returns: pointer to the next in-order node after __x. // Precondition: __x != nullptr. template _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { if (__x->__right_ != nullptr) return __tree_min(__x->__right_); while (!__tree_is_left_child(__x)) __x = __x->__parent_; return __x->__parent_; } // Returns: pointer to the previous in-order node before __x. // Precondition: __x != nullptr. template _NodePtr __tree_prev(_NodePtr __x) _NOEXCEPT { if (__x->__left_ != nullptr) return __tree_max(__x->__left_); while (__tree_is_left_child(__x)) __x = __x->__parent_; return __x->__parent_; } // Returns: pointer to a node which has no children // Precondition: __x != nullptr. template _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { while (true) { if (__x->__left_ != nullptr) { __x = __x->__left_; continue; } if (__x->__right_ != nullptr) { __x = __x->__right_; continue; } break; } return __x; } // Effects: Makes __x->__right_ the subtree root with __x as its left child // while preserving in-order order. // Precondition: __x->__right_ != nullptr template void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { _NodePtr __y = __x->__right_; __x->__right_ = __y->__left_; if (__x->__right_ != nullptr) __x->__right_->__parent_ = __x; __y->__parent_ = __x->__parent_; if (__tree_is_left_child(__x)) __x->__parent_->__left_ = __y; else __x->__parent_->__right_ = __y; __y->__left_ = __x; __x->__parent_ = __y; } // Effects: Makes __x->__left_ the subtree root with __x as its right child // while preserving in-order order. // Precondition: __x->__left_ != nullptr template void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { _NodePtr __y = __x->__left_; __x->__left_ = __y->__right_; if (__x->__left_ != nullptr) __x->__left_->__parent_ = __x; __y->__parent_ = __x->__parent_; if (__tree_is_left_child(__x)) __x->__parent_->__left_ = __y; else __x->__parent_->__right_ = __y; __y->__right_ = __x; __x->__parent_ = __y; } // Effects: Rebalances __root after attaching __x to a leaf. // Precondition: __root != nulptr && __x != nullptr. // __x has no children. // __x == __root or == a direct or indirect child of __root. // If __x were to be unlinked from __root (setting __root to // nullptr if __root == __x), __tree_invariant(__root) == true. // Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_ // may be different than the value passed in as __root. template void __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { __x->__is_black_ = __x == __root; while (__x != __root && !__x->__parent_->__is_black_) { // __x->__parent_ != __root because __x->__parent_->__is_black == false if (__tree_is_left_child(__x->__parent_)) { _NodePtr __y = __x->__parent_->__parent_->__right_; if (__y != nullptr && !__y->__is_black_) { __x = __x->__parent_; __x->__is_black_ = true; __x = __x->__parent_; __x->__is_black_ = __x == __root; __y->__is_black_ = true; } else { if (!__tree_is_left_child(__x)) { __x = __x->__parent_; __tree_left_rotate(__x); } __x = __x->__parent_; __x->__is_black_ = true; __x = __x->__parent_; __x->__is_black_ = false; __tree_right_rotate(__x); break; } } else { _NodePtr __y = __x->__parent_->__parent_->__left_; if (__y != nullptr && !__y->__is_black_) { __x = __x->__parent_; __x->__is_black_ = true; __x = __x->__parent_; __x->__is_black_ = __x == __root; __y->__is_black_ = true; } else { if (__tree_is_left_child(__x)) { __x = __x->__parent_; __tree_right_rotate(__x); } __x = __x->__parent_; __x->__is_black_ = true; __x = __x->__parent_; __x->__is_black_ = false; __tree_left_rotate(__x); break; } } } } // Precondition: __root != nullptr && __z != nullptr. // __tree_invariant(__root) == true. // __z == __root or == a direct or indirect child of __root. // Effects: unlinks __z from the tree rooted at __root, rebalancing as needed. // Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_ // nor any of its children refer to __z. end_node->__left_ // may be different than the value passed in as __root. template void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { // __z will be removed from the tree. Client still needs to destruct/deallocate it // __y is either __z, or if __z has two children, __tree_next(__z). // __y will have at most one child. // __y will be the initial hole in the tree (make the hole at a leaf) _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ? __z : __tree_next(__z); // __x is __y's possibly null single child _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_; // __w is __x's possibly null uncle (will become __x's sibling) _NodePtr __w = nullptr; // link __x to __y's parent, and find __w if (__x != nullptr) __x->__parent_ = __y->__parent_; if (__tree_is_left_child(__y)) { __y->__parent_->__left_ = __x; if (__y != __root) __w = __y->__parent_->__right_; else __root = __x; // __w == nullptr } else { __y->__parent_->__right_ = __x; // __y can't be root if it is a right child __w = __y->__parent_->__left_; } bool __removed_black = __y->__is_black_; // If we didn't remove __z, do so now by splicing in __y for __z, // but copy __z's color. This does not impact __x or __w. if (__y != __z) { // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr __y->__parent_ = __z->__parent_; if (__tree_is_left_child(__z)) __y->__parent_->__left_ = __y; else __y->__parent_->__right_ = __y; __y->__left_ = __z->__left_; __y->__left_->__parent_ = __y; __y->__right_ = __z->__right_; if (__y->__right_ != nullptr) __y->__right_->__parent_ = __y; __y->__is_black_ = __z->__is_black_; if (__root == __z) __root = __y; } // There is no need to rebalance if we removed a red, or if we removed // the last node. if (__removed_black && __root != nullptr) { // Rebalance: // __x has an implicit black color (transferred from the removed __y) // associated with it, no matter what its color is. // If __x is __root (in which case it can't be null), it is supposed // to be black anyway, and if it is doubly black, then the double // can just be ignored. // If __x is red (in which case it can't be null), then it can absorb // the implicit black just by setting its color to black. // Since __y was black and only had one child (which __x points to), __x // is either red with no children, else null, otherwise __y would have // different black heights under left and right pointers. // if (__x == __root || __x != nullptr && !__x->__is_black_) if (__x != nullptr) __x->__is_black_ = true; else { // Else __x isn't root, and is "doubly black", even though it may // be null. __w can not be null here, else the parent would // see a black height >= 2 on the __x side and a black height // of 1 on the __w side (__w must be a non-null black or a red // with a non-null black child). while (true) { if (!__tree_is_left_child(__w)) // if x is left child { if (!__w->__is_black_) { __w->__is_black_ = true; __w->__parent_->__is_black_ = false; __tree_left_rotate(__w->__parent_); // __x is still valid // reset __root only if necessary if (__root == __w->__left_) __root = __w; // reset sibling, and it still can't be null __w = __w->__left_->__right_; } // __w->__is_black_ is now true, __w may have null children if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && (__w->__right_ == nullptr || __w->__right_->__is_black_)) { __w->__is_black_ = false; __x = __w->__parent_; // __x can no longer be null if (__x == __root || !__x->__is_black_) { __x->__is_black_ = true; break; } // reset sibling, and it still can't be null __w = __tree_is_left_child(__x) ? __x->__parent_->__right_ : __x->__parent_->__left_; // continue; } else // __w has a red child { if (__w->__right_ == nullptr || __w->__right_->__is_black_) { // __w left child is non-null and red __w->__left_->__is_black_ = true; __w->__is_black_ = false; __tree_right_rotate(__w); // __w is known not to be root, so root hasn't changed // reset sibling, and it still can't be null __w = __w->__parent_; } // __w has a right red child, left child may be null __w->__is_black_ = __w->__parent_->__is_black_; __w->__parent_->__is_black_ = true; __w->__right_->__is_black_ = true; __tree_left_rotate(__w->__parent_); break; } } else { if (!__w->__is_black_) { __w->__is_black_ = true; __w->__parent_->__is_black_ = false; __tree_right_rotate(__w->__parent_); // __x is still valid // reset __root only if necessary if (__root == __w->__right_) __root = __w; // reset sibling, and it still can't be null __w = __w->__right_->__left_; } // __w->__is_black_ is now true, __w may have null children if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && (__w->__right_ == nullptr || __w->__right_->__is_black_)) { __w->__is_black_ = false; __x = __w->__parent_; // __x can no longer be null if (!__x->__is_black_ || __x == __root) { __x->__is_black_ = true; break; } // reset sibling, and it still can't be null __w = __tree_is_left_child(__x) ? __x->__parent_->__right_ : __x->__parent_->__left_; // continue; } else // __w has a red child { if (__w->__left_ == nullptr || __w->__left_->__is_black_) { // __w right child is non-null and red __w->__right_->__is_black_ = true; __w->__is_black_ = false; __tree_left_rotate(__w); // __w is known not to be root, so root hasn't changed // reset sibling, and it still can't be null __w = __w->__parent_; } // __w has a left red child, right child may be null __w->__is_black_ = __w->__parent_->__is_black_; __w->__parent_->__is_black_ = true; __w->__left_->__is_black_ = true; __tree_right_rotate(__w->__parent_); break; } } } } } } template class __map_node_destructor; template class __tree_node_destructor { typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: allocator_type& __na_; __tree_node_destructor& operator=(const __tree_node_destructor&); public: bool __value_constructed; _LIBCPP_INLINE_VISIBILITY explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT : __na_(__na), __value_constructed(__val) {} _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } template friend class __map_node_destructor; }; // node template class __tree_end_node { public: typedef _Pointer pointer; pointer __left_; _LIBCPP_INLINE_VISIBILITY __tree_end_node() _NOEXCEPT : __left_() {} }; template class __tree_node_base : public __tree_end_node < - typename pointer_traits<_VoidPtr>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__tree_node_base<_VoidPtr> > -#else - rebind<__tree_node_base<_VoidPtr> >::other -#endif + typename __rebind_pointer<_VoidPtr, __tree_node_base<_VoidPtr> >::type > { __tree_node_base(const __tree_node_base&); __tree_node_base& operator=(const __tree_node_base&); public: - typedef typename pointer_traits<_VoidPtr>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__tree_node_base> -#else - rebind<__tree_node_base>::other -#endif - pointer; - typedef typename pointer_traits<_VoidPtr>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - const_pointer; + typedef typename __rebind_pointer<_VoidPtr, __tree_node_base>::type pointer; + typedef typename __rebind_pointer<_VoidPtr, const __tree_node_base>::type const_pointer; + typedef __tree_end_node base; pointer __right_; pointer __parent_; bool __is_black_; _LIBCPP_INLINE_VISIBILITY __tree_node_base() _NOEXCEPT : __right_(), __parent_(), __is_black_(false) {} }; template class __tree_node : public __tree_node_base<_VoidPtr> { public: typedef __tree_node_base<_VoidPtr> base; typedef _Tp value_type; value_type __value_; #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template _LIBCPP_INLINE_VISIBILITY explicit __tree_node(_Args&& ...__args) : __value_(_VSTD::forward<_Args>(__args)...) {} #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) _LIBCPP_INLINE_VISIBILITY explicit __tree_node(const value_type& __v) : __value_(__v) {} #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) }; template class _LIBCPP_TYPE_VIS_ONLY __map_iterator; template class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; template class _LIBCPP_TYPE_VIS_ONLY __tree_iterator { typedef _NodePtr __node_pointer; typedef typename pointer_traits<__node_pointer>::element_type __node; __node_pointer __ptr_; typedef pointer_traits<__node_pointer> __pointer_traits; public: typedef bidirectional_iterator_tag iterator_category; typedef _Tp value_type; typedef _DiffType difference_type; typedef value_type& reference; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __ptr_(nullptr) #endif {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__ptr_->__value_);} _LIBCPP_INLINE_VISIBILITY __tree_iterator& operator++() { __ptr_ = static_cast<__node_pointer>( __tree_next(static_cast(__ptr_))); return *this; } _LIBCPP_INLINE_VISIBILITY __tree_iterator operator++(int) {__tree_iterator __t(*this); ++(*this); return __t;} _LIBCPP_INLINE_VISIBILITY __tree_iterator& operator--() { __ptr_ = static_cast<__node_pointer>( __tree_prev(static_cast(__ptr_))); return *this; } _LIBCPP_INLINE_VISIBILITY __tree_iterator operator--(int) {__tree_iterator __t(*this); --(*this); return __t;} friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) {return __x.__ptr_ == __y.__ptr_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) {return !(__x == __y);} private: _LIBCPP_INLINE_VISIBILITY explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} template friend class __tree; template friend class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __map_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY map; template friend class _LIBCPP_TYPE_VIS_ONLY multimap; template friend class _LIBCPP_TYPE_VIS_ONLY set; template friend class _LIBCPP_TYPE_VIS_ONLY multiset; }; template class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator { typedef _ConstNodePtr __node_pointer; typedef typename pointer_traits<__node_pointer>::element_type __node; __node_pointer __ptr_; typedef pointer_traits<__node_pointer> __pointer_traits; public: typedef bidirectional_iterator_tag iterator_category; typedef _Tp value_type; typedef _DiffType difference_type; typedef const value_type& reference; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, const value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __ptr_(nullptr) #endif {} private: typedef typename remove_const<__node>::type __non_const_node; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__non_const_node> -#else - rebind<__non_const_node>::other -#endif - __non_const_node_pointer; + typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type + __non_const_node_pointer; typedef __tree_iterator __non_const_iterator; public: _LIBCPP_INLINE_VISIBILITY __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__ptr_->__value_);} _LIBCPP_INLINE_VISIBILITY __tree_const_iterator& operator++() { - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - __node_base_pointer; - + typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type + __node_base_pointer; __ptr_ = static_cast<__node_pointer>( __tree_next(static_cast<__node_base_pointer>(__ptr_))); return *this; } _LIBCPP_INLINE_VISIBILITY __tree_const_iterator operator++(int) {__tree_const_iterator __t(*this); ++(*this); return __t;} _LIBCPP_INLINE_VISIBILITY __tree_const_iterator& operator--() { - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - __node_base_pointer; - + typedef typename __rebind_pointer<__node_pointer, typename __node::base>::type + __node_base_pointer; __ptr_ = static_cast<__node_pointer>( __tree_prev(static_cast<__node_base_pointer>(__ptr_))); return *this; } _LIBCPP_INLINE_VISIBILITY __tree_const_iterator operator--(int) {__tree_const_iterator __t(*this); --(*this); return __t;} friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) {return __x.__ptr_ == __y.__ptr_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) {return !(__x == __y);} private: _LIBCPP_INLINE_VISIBILITY explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} template friend class __tree; template friend class _LIBCPP_TYPE_VIS_ONLY map; template friend class _LIBCPP_TYPE_VIS_ONLY multimap; template friend class _LIBCPP_TYPE_VIS_ONLY set; template friend class _LIBCPP_TYPE_VIS_ONLY multiset; template friend class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; }; template class __tree { public: typedef _Tp value_type; typedef _Compare value_compare; typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef typename __alloc_traits::void_pointer __void_pointer; typedef __tree_node __node; typedef __tree_node_base<__void_pointer> __node_base; typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; typedef allocator_traits<__node_allocator> __node_traits; typedef typename __node_traits::pointer __node_pointer; typedef typename __node_traits::pointer __node_const_pointer; typedef typename __node_base::pointer __node_base_pointer; typedef typename __node_base::pointer __node_base_const_pointer; private: typedef typename __node_base::base __end_node_t; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__end_node_t> -#else - rebind<__end_node_t>::other -#endif - __end_node_ptr; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__end_node_t> -#else - rebind<__end_node_t>::other -#endif - __end_node_const_ptr; + typedef typename __rebind_pointer<__node_pointer, __end_node_t>::type + __end_node_ptr; + typedef __end_node_ptr __end_node_const_ptr; __node_pointer __begin_node_; __compressed_pair<__end_node_t, __node_allocator> __pair1_; __compressed_pair __pair3_; public: _LIBCPP_INLINE_VISIBILITY __node_pointer __end_node() _NOEXCEPT { return static_cast<__node_pointer> ( pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()) ); } _LIBCPP_INLINE_VISIBILITY __node_const_pointer __end_node() const _NOEXCEPT { return static_cast<__node_const_pointer> ( pointer_traits<__end_node_const_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first())) ); } _LIBCPP_INLINE_VISIBILITY __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();} private: _LIBCPP_INLINE_VISIBILITY const __node_allocator& __node_alloc() const _NOEXCEPT {return __pair1_.second();} _LIBCPP_INLINE_VISIBILITY __node_pointer& __begin_node() _NOEXCEPT {return __begin_node_;} _LIBCPP_INLINE_VISIBILITY const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;} public: _LIBCPP_INLINE_VISIBILITY allocator_type __alloc() const _NOEXCEPT {return allocator_type(__node_alloc());} private: _LIBCPP_INLINE_VISIBILITY size_type& size() _NOEXCEPT {return __pair3_.first();} public: _LIBCPP_INLINE_VISIBILITY const size_type& size() const _NOEXCEPT {return __pair3_.first();} _LIBCPP_INLINE_VISIBILITY value_compare& value_comp() _NOEXCEPT {return __pair3_.second();} _LIBCPP_INLINE_VISIBILITY const value_compare& value_comp() const _NOEXCEPT {return __pair3_.second();} public: _LIBCPP_INLINE_VISIBILITY __node_pointer __root() _NOEXCEPT {return static_cast<__node_pointer> (__end_node()->__left_);} _LIBCPP_INLINE_VISIBILITY __node_const_pointer __root() const _NOEXCEPT {return static_cast<__node_const_pointer>(__end_node()->__left_);} typedef __tree_iterator iterator; typedef __tree_const_iterator const_iterator; explicit __tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value && is_nothrow_copy_constructible::value); explicit __tree(const allocator_type& __a); __tree(const value_compare& __comp, const allocator_type& __a); __tree(const __tree& __t); __tree& operator=(const __tree& __t); template void __assign_unique(_InputIterator __first, _InputIterator __last); template void __assign_multi(_InputIterator __first, _InputIterator __last); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible::value); __tree(__tree&& __t, const allocator_type& __a); __tree& operator=(__tree&& __t) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable<__node_allocator>::value); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES ~__tree(); _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(__begin_node());} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return iterator(__end_node());} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __node_traits::max_size(__node_alloc());} void clear() _NOEXCEPT; void swap(__tree& __t) _NOEXCEPT_( __is_nothrow_swappable::value #if _LIBCPP_STD_VER <= 11 && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) #endif ); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template pair __emplace_unique(_Args&&... __args); template iterator __emplace_multi(_Args&&... __args); template iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args); template iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); #endif // _LIBCPP_HAS_NO_VARIADICS template pair __insert_unique(_Vp&& __v); template iterator __insert_unique(const_iterator __p, _Vp&& __v); template iterator __insert_multi(_Vp&& __v); template iterator __insert_multi(const_iterator __p, _Vp&& __v); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES pair __insert_unique(const value_type& __v); iterator __insert_unique(const_iterator __p, const value_type& __v); iterator __insert_multi(const value_type& __v); iterator __insert_multi(const_iterator __p, const value_type& __v); +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + pair __insert_unique( value_type&& __v); + iterator __insert_unique(const_iterator __p, value_type&& __v); + iterator __insert_multi( value_type&& __v); + iterator __insert_multi(const_iterator __p, value_type&& __v); +#endif + pair __node_insert_unique(__node_pointer __nd); iterator __node_insert_unique(const_iterator __p, __node_pointer __nd); iterator __node_insert_multi(__node_pointer __nd); iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); iterator erase(const_iterator __p); iterator erase(const_iterator __f, const_iterator __l); template size_type __erase_unique(const _Key& __k); template size_type __erase_multi(const _Key& __k); void __insert_node_at(__node_base_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node); template iterator find(const _Key& __v); template const_iterator find(const _Key& __v) const; template size_type __count_unique(const _Key& __k) const; template size_type __count_multi(const _Key& __k) const; template _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const _Key& __v) {return __lower_bound(__v, __root(), __end_node());} template iterator __lower_bound(const _Key& __v, __node_pointer __root, __node_pointer __result); template _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const _Key& __v) const {return __lower_bound(__v, __root(), __end_node());} template const_iterator __lower_bound(const _Key& __v, __node_const_pointer __root, __node_const_pointer __result) const; template _LIBCPP_INLINE_VISIBILITY iterator upper_bound(const _Key& __v) {return __upper_bound(__v, __root(), __end_node());} template iterator __upper_bound(const _Key& __v, __node_pointer __root, __node_pointer __result); template _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const _Key& __v) const {return __upper_bound(__v, __root(), __end_node());} template const_iterator __upper_bound(const _Key& __v, __node_const_pointer __root, __node_const_pointer __result) const; template pair __equal_range_unique(const _Key& __k); template pair __equal_range_unique(const _Key& __k) const; template pair __equal_range_multi(const _Key& __k); template pair __equal_range_multi(const _Key& __k) const; typedef __tree_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; __node_holder remove(const_iterator __p) _NOEXCEPT; private: typename __node_base::pointer& __find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v); typename __node_base::pointer& __find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v); typename __node_base::pointer& __find_leaf(const_iterator __hint, typename __node_base::pointer& __parent, const value_type& __v); template typename __node_base::pointer& __find_equal(typename __node_base::pointer& __parent, const _Key& __v); template typename __node_base::pointer& __find_equal(const_iterator __hint, typename __node_base::pointer& __parent, const _Key& __v); #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template __node_holder __construct_node(_Args&& ...__args); #else // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) __node_holder __construct_node(const value_type& __v); #endif void destroy(__node_pointer __nd) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t) {__copy_assign_alloc(__t, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t, true_type) {__node_alloc() = __t.__node_alloc();} _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t, false_type) {} void __move_assign(__tree& __t, false_type); void __move_assign(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value && is_nothrow_move_assignable<__node_allocator>::value); _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__tree& __t) _NOEXCEPT_( !__node_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<__node_allocator>::value) {__move_assign_alloc(__t, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__node_alloc() = _VSTD::move(__t.__node_alloc());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {} __node_pointer __detach(); static __node_pointer __detach(__node_pointer); template friend class _LIBCPP_TYPE_VIS_ONLY map; template friend class _LIBCPP_TYPE_VIS_ONLY multimap; }; template __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value && is_nothrow_copy_constructible::value) : __pair3_(0, __comp) { __begin_node() = __end_node(); } template __tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) : __begin_node_(__node_pointer()), __pair1_(__node_allocator(__a)), __pair3_(0) { __begin_node() = __end_node(); } template __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, const allocator_type& __a) : __begin_node_(__node_pointer()), __pair1_(__node_allocator(__a)), __pair3_(0, __comp) { __begin_node() = __end_node(); } // Precondition: size() != 0 template typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::__detach() { __node_pointer __cache = __begin_node(); __begin_node() = __end_node(); __end_node()->__left_->__parent_ = nullptr; __end_node()->__left_ = nullptr; size() = 0; // __cache->__left_ == nullptr if (__cache->__right_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__right_); // __cache->__left_ == nullptr // __cache->__right_ == nullptr return __cache; } // Precondition: __cache != nullptr // __cache->left_ == nullptr // __cache->right_ == nullptr // This is no longer a red-black tree template typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache) { if (__cache->__parent_ == nullptr) return nullptr; if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) { __cache->__parent_->__left_ = nullptr; __cache = static_cast<__node_pointer>(__cache->__parent_); if (__cache->__right_ == nullptr) return __cache; return static_cast<__node_pointer>(__tree_leaf(__cache->__right_)); } // __cache is right child __cache->__parent_->__right_ = nullptr; __cache = static_cast<__node_pointer>(__cache->__parent_); if (__cache->__left_ == nullptr) return __cache; return static_cast<__node_pointer>(__tree_leaf(__cache->__left_)); } template __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) { if (this != &__t) { value_comp() = __t.value_comp(); __copy_assign_alloc(__t); __assign_multi(__t.begin(), __t.end()); } return *this; } template template void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last) { if (size() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__value_ = *__first; __node_pointer __next = __detach(__cache); __node_insert_unique(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS if (__cache != nullptr) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); } } for (; __first != __last; ++__first) __insert_unique(*__first); } template template void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) { if (size() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__value_ = *__first; __node_pointer __next = __detach(__cache); __node_insert_multi(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS if (__cache != nullptr) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); } } for (; __first != __last; ++__first) __insert_multi(*__first); } template __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) : __begin_node_(__node_pointer()), __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), __pair3_(0, __t.value_comp()) { __begin_node() = __end_node(); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible::value) : __begin_node_(_VSTD::move(__t.__begin_node_)), __pair1_(_VSTD::move(__t.__pair1_)), __pair3_(_VSTD::move(__t.__pair3_)) { if (size() == 0) __begin_node() = __end_node(); else { __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); __t.__begin_node() = __t.__end_node(); __t.__end_node()->__left_ = nullptr; __t.size() = 0; } } template __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) : __pair1_(__node_allocator(__a)), __pair3_(0, _VSTD::move(__t.value_comp())) { if (__a == __t.__alloc()) { if (__t.size() == 0) __begin_node() = __end_node(); else { __begin_node() = __t.__begin_node(); __end_node()->__left_ = __t.__end_node()->__left_; __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); size() = __t.size(); __t.__begin_node() = __t.__end_node(); __t.__end_node()->__left_ = nullptr; __t.size() = 0; } } else { __begin_node() = __end_node(); } } template void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value && is_nothrow_move_assignable<__node_allocator>::value) { destroy(static_cast<__node_pointer>(__end_node()->__left_)); __begin_node_ = __t.__begin_node_; __pair1_.first() = __t.__pair1_.first(); __move_assign_alloc(__t); __pair3_ = _VSTD::move(__t.__pair3_); if (size() == 0) __begin_node() = __end_node(); else { __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); __t.__begin_node() = __t.__end_node(); __t.__end_node()->__left_ = nullptr; __t.size() = 0; } } template void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { if (__node_alloc() == __t.__node_alloc()) __move_assign(__t, true_type()); else { value_comp() = _VSTD::move(__t.value_comp()); const_iterator __e = end(); if (size() != 0) { __node_pointer __cache = __detach(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS while (__cache != nullptr && __t.size() != 0) { __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_); __node_pointer __next = __detach(__cache); __node_insert_multi(__cache); __cache = __next; } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); throw; } #endif // _LIBCPP_NO_EXCEPTIONS if (__cache != nullptr) { while (__cache->__parent_ != nullptr) __cache = static_cast<__node_pointer>(__cache->__parent_); destroy(__cache); } } while (__t.size() != 0) __insert_multi(__e, _VSTD::move(__t.remove(__t.begin())->__value_)); } } template __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable<__node_allocator>::value) { __move_assign(__t, integral_constant()); return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template __tree<_Tp, _Compare, _Allocator>::~__tree() { destroy(__root()); } template void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT { if (__nd != nullptr) { destroy(static_cast<__node_pointer>(__nd->__left_)); destroy(static_cast<__node_pointer>(__nd->__right_)); __node_allocator& __na = __node_alloc(); __node_traits::destroy(__na, _VSTD::addressof(__nd->__value_)); __node_traits::deallocate(__na, __nd, 1); } } template void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) _NOEXCEPT_( __is_nothrow_swappable::value #if _LIBCPP_STD_VER <= 11 && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) #endif ) { using _VSTD::swap; swap(__begin_node_, __t.__begin_node_); swap(__pair1_.first(), __t.__pair1_.first()); __swap_allocator(__node_alloc(), __t.__node_alloc()); __pair3_.swap(__t.__pair3_); if (size() == 0) __begin_node() = __end_node(); else __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node()); if (__t.size() == 0) __t.__begin_node() = __t.__end_node(); else __t.__end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node()); } template void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { destroy(__root()); size() = 0; __begin_node() = __end_node(); __end_node()->__left_ = nullptr; } // Find lower_bound place to insert // Set __parent to parent of null leaf // Return reference to null leaf template typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(typename __node_base::pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { while (true) { if (value_comp()(__nd->__value_, __v)) { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__right_; } } else { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__left_; } } } } __parent = static_cast<__node_base_pointer>(__end_node()); return __parent->__left_; } // Find upper_bound place to insert // Set __parent to parent of null leaf // Return reference to null leaf template typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(typename __node_base::pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { while (true) { if (value_comp()(__v, __nd->__value_)) { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__left_; } } else { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__right_; } } } } __parent = static_cast<__node_base_pointer>(__end_node()); return __parent->__left_; } // Find leaf place to insert closest to __hint // First check prior to __hint. // Next check after __hint. // Next do O(log N) search. // Set __parent to parent of null leaf // Return reference to null leaf template typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint, typename __node_base::pointer& __parent, const value_type& __v) { if (__hint == end() || !value_comp()(*__hint, __v)) // check before { // __v <= *__hint const_iterator __prior = __hint; if (__prior == begin() || !value_comp()(__v, *--__prior)) { // *prev(__hint) <= __v <= *__hint if (__hint.__ptr_->__left_ == nullptr) { __parent = static_cast<__node_base_pointer>(__hint.__ptr_); return __parent->__left_; } else { __parent = static_cast<__node_base_pointer>(__prior.__ptr_); return __parent->__right_; } } // __v < *prev(__hint) return __find_leaf_high(__parent, __v); } // else __v > *__hint return __find_leaf_low(__parent, __v); } // Find place to insert if __v doesn't exist // Set __parent to parent of null leaf // Return reference to null leaf // If __v exists, set parent to node of __v and return reference to node of __v template template typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal(typename __node_base::pointer& __parent, const _Key& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { while (true) { if (value_comp()(__v, __nd->__value_)) { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__left_; } } else if (value_comp()(__nd->__value_, __v)) { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__right_; } } else { __parent = static_cast<__node_base_pointer>(__nd); return __parent; } } } __parent = static_cast<__node_base_pointer>(__end_node()); return __parent->__left_; } // Find place to insert if __v doesn't exist // First check prior to __hint. // Next check after __hint. // Next do O(log N) search. // Set __parent to parent of null leaf // Return reference to null leaf // If __v exists, set parent to node of __v and return reference to node of __v template template typename __tree<_Tp, _Compare, _Allocator>::__node_base::pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, typename __node_base::pointer& __parent, const _Key& __v) { if (__hint == end() || value_comp()(__v, *__hint)) // check before { // __v < *__hint const_iterator __prior = __hint; if (__prior == begin() || value_comp()(*--__prior, __v)) { // *prev(__hint) < __v < *__hint if (__hint.__ptr_->__left_ == nullptr) { __parent = static_cast<__node_base_pointer>(__hint.__ptr_); return __parent->__left_; } else { __parent = static_cast<__node_base_pointer>(__prior.__ptr_); return __parent->__right_; } } // __v <= *prev(__hint) return __find_equal(__parent, __v); } else if (value_comp()(*__hint, __v)) // check after { // *__hint < __v const_iterator __next = _VSTD::next(__hint); if (__next == end() || value_comp()(__v, *__next)) { // *__hint < __v < *_VSTD::next(__hint) if (__hint.__ptr_->__right_ == nullptr) { __parent = static_cast<__node_base_pointer>(__hint.__ptr_); return __parent->__right_; } else { __parent = static_cast<__node_base_pointer>(__next.__ptr_); return __parent->__left_; } } // *next(__hint) <= __v return __find_equal(__parent, __v); } // else __v == *__hint __parent = static_cast<__node_base_pointer>(__hint.__ptr_); return __parent; } template void __tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) { __new_node->__left_ = nullptr; __new_node->__right_ = nullptr; __new_node->__parent_ = __parent; __child = __new_node; if (__begin_node()->__left_ != nullptr) __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_); __tree_balance_after_insert(__end_node()->__left_, __child); ++size(); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__value_constructed = true; return __h; } template template pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__emplace_unique(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __h->__value_); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } return pair(iterator(__r), __inserted); } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__p, __parent, __h->__value_); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return iterator(__r); } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } #endif // _LIBCPP_HAS_NO_VARIADICS +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__insert_unique(value_type&& __v) +{ + __node_holder __h = __construct_node(_VSTD::forward(__v)); + pair __r = __node_insert_unique(__h.get()); + if (__r.second) + __h.release(); + return __r; +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, value_type&& __v) +{ + __node_holder __h = __construct_node(_VSTD::forward(__v)); + iterator __r = __node_insert_unique(__p, __h.get()); + if (__r.__ptr_ == __h.get()) + __h.release(); + return __r; +} + template template pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__insert_unique(_Vp&& __v) { __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); pair __r = __node_insert_unique(__h.get()); if (__r.second) __h.release(); return __r; } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, _Vp&& __v) { __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); iterator __r = __node_insert_unique(__p, __h.get()); if (__r.__ptr_ == __h.get()) __h.release(); return __r; } +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__insert_multi(value_type&& __v) +{ + __node_base_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, __v); + __node_holder __h = __construct_node(_VSTD::forward(__v)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(__h.release()); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, value_type&& __v) +{ + __node_base_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, __v); + __node_holder __h = __construct_node(_VSTD::forward(__v)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(__h.release()); +} + template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_multi(_Vp&& __v) { __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __h->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(__h.release()); } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, _Vp&& __v) { __node_holder __h = __construct_node(_VSTD::forward<_Vp>(__v)); __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(__h.release()); } #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(const value_type& __v) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); __h.get_deleter().__value_constructed = true; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__insert_unique(const value_type& __v) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __v); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __node_holder __h = __construct_node(__v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } return pair(iterator(__r), __inserted); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_unique(const_iterator __p, const value_type& __v) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__p, __parent, __v); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __node_holder __h = __construct_node(__v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return iterator(__r); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_multi(const value_type& __v) { __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __v); __node_holder __h = __construct_node(__v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(__h.release()); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const value_type& __v) { __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __v); __node_holder __h = __construct_node(__v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(__h.release()); } template pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __nd->__value_); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); __r = __nd; __inserted = true; } return pair(iterator(__r), __inserted); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p, __node_pointer __nd) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); __r = __nd; } return iterator(__r); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) { __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); return iterator(__nd); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) { __node_base_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__value_); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); return iterator(__nd); } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) { __node_pointer __np = __p.__ptr_; iterator __r(__np); ++__r; if (__begin_node() == __np) __begin_node() = __r.__ptr_; --size(); __node_allocator& __na = __node_alloc(); __tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__np)); __node_traits::destroy(__na, const_cast(_VSTD::addressof(*__p))); __node_traits::deallocate(__na, __np, 1); return __r; } template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) { while (__f != __l) __f = erase(__f); return iterator(__l.__ptr_); } template template typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) { iterator __i = find(__k); if (__i == end()) return 0; erase(__i); return 1; } template template typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { pair __p = __equal_range_multi(__k); size_type __r = 0; for (; __p.first != __p.second; ++__r) __p.first = erase(__p.first); return __r; } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) { iterator __p = __lower_bound(__v, __root(), __end_node()); if (__p != end() && !value_comp()(__v, *__p)) return __p; return end(); } template template typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const { const_iterator __p = __lower_bound(__v, __root(), __end_node()); if (__p != end() && !value_comp()(__v, *__p)) return __p; return end(); } template template typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_const_pointer __result = __end_node(); __node_const_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_const_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_const_pointer>(__rt->__right_); else return 1; } return 0; } template template typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __node_const_pointer __result = __end_node(); __node_const_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_const_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_const_pointer>(__rt->__right_); else return _VSTD::distance( __lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt), __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result) ); } return 0; } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, __node_pointer __root, __node_pointer __result) { while (__root != nullptr) { if (!value_comp()(__root->__value_, __v)) { __result = __root; __root = static_cast<__node_pointer>(__root->__left_); } else __root = static_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, __node_const_pointer __root, __node_const_pointer __result) const { while (__root != nullptr) { if (!value_comp()(__root->__value_, __v)) { __result = __root; __root = static_cast<__node_const_pointer>(__root->__left_); } else __root = static_cast<__node_const_pointer>(__root->__right_); } return const_iterator(__result); } template template typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, __node_pointer __root, __node_pointer __result) { while (__root != nullptr) { if (value_comp()(__v, __root->__value_)) { __result = __root; __root = static_cast<__node_pointer>(__root->__left_); } else __root = static_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, __node_const_pointer __root, __node_const_pointer __result) const { while (__root != nullptr) { if (value_comp()(__v, __root->__value_)) { __result = __root; __root = static_cast<__node_const_pointer>(__root->__left_); } else __root = static_cast<__node_const_pointer>(__root->__right_); } return const_iterator(__result); } template template pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { typedef pair _Pp; __node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), iterator( __rt->__right_ != nullptr ? static_cast<__node_pointer>(__tree_min(__rt->__right_)) : __result)); } return _Pp(iterator(__result), iterator(__result)); } template template pair::const_iterator, typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { typedef pair _Pp; __node_const_pointer __result = __end_node(); __node_const_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_const_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_const_pointer>(__rt->__right_); else return _Pp(const_iterator(__rt), const_iterator( __rt->__right_ != nullptr ? static_cast<__node_const_pointer>(__tree_min(__rt->__right_)) : __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template template pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { typedef pair _Pp; __node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), __rt), __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); } return _Pp(iterator(__result), iterator(__result)); } template template pair::const_iterator, typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { typedef pair _Pp; __node_const_pointer __result = __end_node(); __node_const_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { __result = __rt; __rt = static_cast<__node_const_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) __rt = static_cast<__node_const_pointer>(__rt->__right_); else return _Pp(__lower_bound(__k, static_cast<__node_const_pointer>(__rt->__left_), __rt), __upper_bound(__k, static_cast<__node_const_pointer>(__rt->__right_), __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT { __node_pointer __np = __p.__ptr_; if (__begin_node() == __np) { if (__np->__right_ != nullptr) __begin_node() = static_cast<__node_pointer>(__np->__right_); else __begin_node() = static_cast<__node_pointer>(__np->__parent_); } --size(); __tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__np)); return __node_holder(__np, _Dp(__node_alloc(), true)); } template inline _LIBCPP_INLINE_VISIBILITY void swap(__tree<_Tp, _Compare, _Allocator>& __x, __tree<_Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TREE diff --git a/include/ext/hash_map b/include/ext/hash_map index 0e4ab6910eb5..3ac27b2ca330 100644 --- a/include/ext/hash_map +++ b/include/ext/hash_map @@ -1,994 +1,982 @@ // -*- C++ -*- //===-------------------------- hash_map ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_HASH_MAP #define _LIBCPP_HASH_MAP /* hash_map synopsis namespace __gnu_cxx { template , class Pred = equal_to, class Alloc = allocator>> class hash_map { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; explicit hash_map(size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template hash_map(InputIterator f, InputIterator l, size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); hash_map(const hash_map&); ~hash_map(); hash_map& operator=(const hash_map&); allocator_type get_allocator() const; bool empty() const; size_type size() const; size_type max_size() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; pair insert(const value_type& obj); template void insert(InputIterator first, InputIterator last); void erase(const_iterator position); size_type erase(const key_type& k); void erase(const_iterator first, const_iterator last); void clear(); void swap(hash_map&); hasher hash_funct() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; mapped_type& operator[](const key_type& k); size_type bucket_count() const; size_type max_bucket_count() const; size_type elems_in_bucket(size_type n) const; void resize(size_type n); }; template void swap(hash_map& x, hash_map& y); template bool operator==(const hash_map& x, const hash_map& y); template bool operator!=(const hash_map& x, const hash_map& y); template , class Pred = equal_to, class Alloc = allocator>> class hash_multimap { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; explicit hash_multimap(size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template hash_multimap(InputIterator f, InputIterator l, size_type n = 193, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit hash_multimap(const allocator_type&); hash_multimap(const hash_multimap&); ~hash_multimap(); hash_multimap& operator=(const hash_multimap&); allocator_type get_allocator() const; bool empty() const; size_type size() const; size_type max_size() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; iterator insert(const value_type& obj); template void insert(InputIterator first, InputIterator last); void erase(const_iterator position); size_type erase(const key_type& k); void erase(const_iterator first, const_iterator last); void clear(); void swap(hash_multimap&); hasher hash_funct() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; size_type bucket_count() const; size_type max_bucket_count() const; size_type elems_in_bucket(size_type n) const; void resize(size_type n); }; template void swap(hash_multimap& x, hash_multimap& y); template bool operator==(const hash_multimap& x, const hash_multimap& y); template bool operator!=(const hash_multimap& x, const hash_multimap& y); } // __gnu_cxx */ #include <__config> #include <__hash_table> #include #include #include #include #if __DEPRECATED #if defined(_MSC_VER) && ! defined(__clang__) _LIBCPP_WARNING("Use of the header is deprecated. Migrate to ") #else # warning Use of the header is deprecated. Migrate to #endif #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif namespace __gnu_cxx { using namespace std; template ::value && !__libcpp_is_final<_Hash>::value > class __hash_map_hasher : private _Hash { public: _LIBCPP_INLINE_VISIBILITY __hash_map_hasher() : _Hash() {} _LIBCPP_INLINE_VISIBILITY __hash_map_hasher(const _Hash& __h) : _Hash(__h) {} _LIBCPP_INLINE_VISIBILITY const _Hash& hash_function() const {return *this;} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Tp& __x) const {return static_cast(*this)(__x.first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const typename _Tp::first_type& __x) const {return static_cast(*this)(__x);} }; template class __hash_map_hasher<_Tp, _Hash, false> { _Hash __hash_; public: _LIBCPP_INLINE_VISIBILITY __hash_map_hasher() : __hash_() {} _LIBCPP_INLINE_VISIBILITY __hash_map_hasher(const _Hash& __h) : __hash_(__h) {} _LIBCPP_INLINE_VISIBILITY const _Hash& hash_function() const {return __hash_;} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Tp& __x) const {return __hash_(__x.first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const typename _Tp::first_type& __x) const {return __hash_(__x);} }; template ::value && !__libcpp_is_final<_Pred>::value > class __hash_map_equal : private _Pred { public: _LIBCPP_INLINE_VISIBILITY __hash_map_equal() : _Pred() {} _LIBCPP_INLINE_VISIBILITY __hash_map_equal(const _Pred& __p) : _Pred(__p) {} _LIBCPP_INLINE_VISIBILITY const _Pred& key_eq() const {return *this;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const {return static_cast(*this)(__x.first, __y.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {return static_cast(*this)(__x, __y.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {return static_cast(*this)(__x.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {return static_cast(*this)(__x, __y);} }; template class __hash_map_equal<_Tp, _Pred, false> { _Pred __pred_; public: _LIBCPP_INLINE_VISIBILITY __hash_map_equal() : __pred_() {} _LIBCPP_INLINE_VISIBILITY __hash_map_equal(const _Pred& __p) : __pred_(__p) {} _LIBCPP_INLINE_VISIBILITY const _Pred& key_eq() const {return __pred_;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const {return __pred_(__x.first, __y.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {return __pred_(__x, __y.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {return __pred_(__x.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {return __pred_(__x, __y);} }; template class __hash_map_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: typedef typename value_type::first_type first_type; typedef typename value_type::second_type second_type; 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) : __na_(__na), __first_constructed(false), __second_constructed(false) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(__hash_node_destructor&& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { __x.__value_constructed = false; } #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(const __hash_node_destructor& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { const_cast(__x.__value_constructed) = false; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) { if (__second_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.second)); if (__first_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator { _HashIterator __i_; - typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::first_type key_type; typedef typename _HashIterator::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + pointer; _LIBCPP_INLINE_VISIBILITY __hash_map_iterator() {} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator(_HashIterator __i) : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return *operator->();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return (pointer)__i_.operator->();} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator operator++(int) { __hash_map_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY hash_map; template friend class _LIBCPP_TYPE_VIS_ONLY hash_multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; }; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator { _HashIterator __i_; - typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::first_type key_type; typedef typename _HashIterator::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef const value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + pointer; _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator() {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator(_HashIterator __i) : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator( __hash_map_iterator __i) : __i_(__i.__i_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return *operator->();} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return (pointer)__i_.operator->();} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator operator++(int) { __hash_map_const_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY hash_map; template friend class _LIBCPP_TYPE_VIS_ONLY hash_multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; }; template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TYPE_VIS_ONLY hash_map { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Tp data_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; private: typedef pair __value_type; typedef __hash_map_hasher<__value_type, hasher> __hasher; typedef __hash_map_equal<__value_type, key_equal> __key_equal; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_pointer __node_pointer; typedef typename __table::__node_const_pointer __node_const_pointer; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; _LIBCPP_INLINE_VISIBILITY hash_map() {__table_.rehash(193);} explicit hash_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template hash_map(_InputIterator __first, _InputIterator __last); template hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); hash_map(const hash_map& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const {return allocator_type(__table_.__node_alloc());} _LIBCPP_INLINE_VISIBILITY bool empty() const {return __table_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const {return __table_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const {return __table_.max_size();} _LIBCPP_INLINE_VISIBILITY iterator begin() {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const {return __table_.end();} _LIBCPP_INLINE_VISIBILITY pair insert(const value_type& __x) {return __table_.__insert_unique(__x);} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator, const value_type& __x) {return insert(__x).first;} template void insert(_InputIterator __first, _InputIterator __last); _LIBCPP_INLINE_VISIBILITY void erase(const_iterator __p) {__table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __table_.__erase_unique(__k);} _LIBCPP_INLINE_VISIBILITY void erase(const_iterator __first, const_iterator __last) {__table_.erase(__first.__i_, __last.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() {__table_.clear();} _LIBCPP_INLINE_VISIBILITY void swap(hash_map& __u) {__table_.swap(__u.__table_);} _LIBCPP_INLINE_VISIBILITY hasher hash_funct() 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);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} mapped_type& operator[](const key_type& __k); _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const {return __table_.bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const {return __table_.max_bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type elems_in_bucket(size_type __n) const {return __table_.bucket_size(__n);} _LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {__table_.rehash(__n);} private: __node_holder __construct_node(const key_type& __k); }; template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); } template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last) { __table_.rehash(193); insert(__first, __last); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); insert(__first, __last); } template template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); insert(__first, __last); } template hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map( const hash_map& __u) : __table_(__u.__table_) { __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(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_.first), __k); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.second)); __h.get_deleter().__second_constructed = true; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } template template inline _LIBCPP_INLINE_VISIBILITY void hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_unique(*__first); } template _Tp& hash_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(__k); pair __r = __table_.__node_insert_unique(__h.get()); __h.release(); return __r.first->second; } template inline _LIBCPP_INLINE_VISIBILITY void swap(hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { __x.swap(__y); } template bool operator==(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) { const_iterator __j = __y.find(__i->first); if (__j == __ey || !(*__i == *__j)) return false; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TYPE_VIS_ONLY hash_multimap { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Tp data_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; private: typedef pair __value_type; typedef __hash_map_hasher<__value_type, hasher> __hasher; typedef __hash_map_equal<__value_type, key_equal> __key_equal; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; _LIBCPP_INLINE_VISIBILITY hash_multimap() {__table_.rehash(193);} explicit hash_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template hash_multimap(_InputIterator __first, _InputIterator __last); template hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); hash_multimap(const hash_multimap& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const {return allocator_type(__table_.__node_alloc());} _LIBCPP_INLINE_VISIBILITY bool empty() const {return __table_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const {return __table_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const {return __table_.max_size();} _LIBCPP_INLINE_VISIBILITY iterator begin() {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() {return __table_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const {return __table_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const {return __table_.end();} _LIBCPP_INLINE_VISIBILITY iterator insert(const value_type& __x) {return __table_.__insert_multi(__x);} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator, const value_type& __x) {return insert(__x);} template void insert(_InputIterator __first, _InputIterator __last); _LIBCPP_INLINE_VISIBILITY void erase(const_iterator __p) {__table_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __table_.__erase_multi(__k);} _LIBCPP_INLINE_VISIBILITY void erase(const_iterator __first, const_iterator __last) {__table_.erase(__first.__i_, __last.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() {__table_.clear();} _LIBCPP_INLINE_VISIBILITY void swap(hash_multimap& __u) {__table_.swap(__u.__table_);} _LIBCPP_INLINE_VISIBILITY hasher hash_funct() 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);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const {return __table_.bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const {return __table_.max_bucket_count();} _LIBCPP_INLINE_VISIBILITY size_type elems_in_bucket(size_type __n) const {return __table_.bucket_size(__n);} _LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {__table_.rehash(__n);} }; template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); } template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last) { __table_.rehash(193); insert(__first, __last); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { __table_.rehash(__n); insert(__first, __last); } template template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { __table_.rehash(__n); insert(__first, __last); } template hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap( const hash_multimap& __u) : __table_(__u.__table_) { __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template template inline _LIBCPP_INLINE_VISIBILITY void hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_multi(*__first); } template inline _LIBCPP_INLINE_VISIBILITY void swap(hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { __x.swap(__y); } template bool operator==(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; typedef pair _EqRng; for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) { _EqRng __xeq = __x.equal_range(__i->first); _EqRng __yeq = __y.equal_range(__i->first); if (_VSTD::distance(__xeq.first, __xeq.second) != _VSTD::distance(__yeq.first, __yeq.second) || !_VSTD::is_permutation(__xeq.first, __xeq.second, __yeq.first)) return false; __i = __xeq.second; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } } // __gnu_cxx #endif // _LIBCPP_HASH_MAP diff --git a/include/forward_list b/include/forward_list index adbc32cf861c..4f9ecf49bd58 100644 --- a/include/forward_list +++ b/include/forward_list @@ -1,1652 +1,1628 @@ // -*- C++ -*- //===----------------------- forward_list ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_FORWARD_LIST #define _LIBCPP_FORWARD_LIST /* forward_list synopsis namespace std { template > class forward_list { public: typedef T value_type; typedef Allocator allocator_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef
iterator; typedef
const_iterator; forward_list() noexcept(is_nothrow_default_constructible::value); explicit forward_list(const allocator_type& a); explicit forward_list(size_type n); explicit forward_list(size_type n, const allocator_type& a); // C++14 forward_list(size_type n, const value_type& v); forward_list(size_type n, const value_type& v, const allocator_type& a); template forward_list(InputIterator first, InputIterator last); template forward_list(InputIterator first, InputIterator last, const allocator_type& a); forward_list(const forward_list& x); forward_list(const forward_list& x, const allocator_type& a); forward_list(forward_list&& x) noexcept(is_nothrow_move_constructible::value); forward_list(forward_list&& x, const allocator_type& a); forward_list(initializer_list il); forward_list(initializer_list il, const allocator_type& a); ~forward_list(); forward_list& operator=(const forward_list& x); forward_list& operator=(forward_list&& x) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value); forward_list& operator=(initializer_list il); template void assign(InputIterator first, InputIterator last); void assign(size_type n, const value_type& v); void assign(initializer_list il); allocator_type get_allocator() const noexcept; iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept; bool empty() const noexcept; size_type max_size() const noexcept; reference front(); const_reference front() const; template void emplace_front(Args&&... args); void push_front(const value_type& v); void push_front(value_type&& v); void pop_front(); template iterator emplace_after(const_iterator p, Args&&... args); iterator insert_after(const_iterator p, const value_type& v); iterator insert_after(const_iterator p, value_type&& v); iterator insert_after(const_iterator p, size_type n, const value_type& v); template iterator insert_after(const_iterator p, InputIterator first, InputIterator last); iterator insert_after(const_iterator p, initializer_list il); iterator erase_after(const_iterator p); iterator erase_after(const_iterator first, const_iterator last); void swap(forward_list& x) noexcept(allocator_traits::is_always_equal::value); // C++17 void resize(size_type n); void resize(size_type n, const value_type& v); void clear() noexcept; void splice_after(const_iterator p, forward_list& x); void splice_after(const_iterator p, forward_list&& x); void splice_after(const_iterator p, forward_list& x, const_iterator i); void splice_after(const_iterator p, forward_list&& x, const_iterator i); void splice_after(const_iterator p, forward_list& x, const_iterator first, const_iterator last); void splice_after(const_iterator p, forward_list&& x, const_iterator first, const_iterator last); void remove(const value_type& v); template void remove_if(Predicate pred); void unique(); template void unique(BinaryPredicate binary_pred); void merge(forward_list& x); void merge(forward_list&& x); template void merge(forward_list& x, Compare comp); template void merge(forward_list&& x, Compare comp); void sort(); template void sort(Compare comp); void reverse() noexcept; }; template bool operator==(const forward_list& x, const forward_list& y); template bool operator< (const forward_list& x, const forward_list& y); template bool operator!=(const forward_list& x, const forward_list& y); template bool operator> (const forward_list& x, const forward_list& y); template bool operator>=(const forward_list& x, const forward_list& y); template bool operator<=(const forward_list& x, const forward_list& y); template void swap(forward_list& x, forward_list& y) noexcept(noexcept(x.swap(y))); } // std */ #include <__config> #include #include #include #include #include #include <__undef_min_max> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template struct __forward_list_node; template struct __forward_begin_node { typedef _NodePtr pointer; pointer __next_; _LIBCPP_INLINE_VISIBILITY __forward_begin_node() : __next_(nullptr) {} }; template struct _LIBCPP_HIDDEN __begin_node_of { - typedef __forward_begin_node - < - typename pointer_traits<_VoidPtr>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__forward_list_node<_Tp, _VoidPtr> > -#else - rebind<__forward_list_node<_Tp, _VoidPtr> >::other -#endif - > type; + typedef __forward_begin_node< + typename __rebind_pointer<_VoidPtr, __forward_list_node<_Tp, _VoidPtr> >::type + > type; }; template struct __forward_list_node : public __begin_node_of<_Tp, _VoidPtr>::type { typedef _Tp value_type; value_type __value_; }; template > class _LIBCPP_TYPE_VIS_ONLY forward_list; template class _LIBCPP_TYPE_VIS_ONLY __forward_list_const_iterator; template class _LIBCPP_TYPE_VIS_ONLY __forward_list_iterator { typedef _NodePtr __node_pointer; __node_pointer __ptr_; _LIBCPP_INLINE_VISIBILITY explicit __forward_list_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} template friend class _LIBCPP_TYPE_VIS_ONLY forward_list; template friend class _LIBCPP_TYPE_VIS_ONLY __forward_list_const_iterator; public: typedef forward_iterator_tag iterator_category; typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type; typedef value_type& reference; typedef typename pointer_traits<__node_pointer>::difference_type difference_type; - typedef typename pointer_traits<__node_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __forward_list_iterator() _NOEXCEPT : __ptr_(nullptr) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__ptr_->__value_);} _LIBCPP_INLINE_VISIBILITY __forward_list_iterator& operator++() { __ptr_ = __ptr_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __forward_list_iterator operator++(int) { __forward_list_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {return __x.__ptr_ == __y.__ptr_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {return !(__x == __y);} }; template class _LIBCPP_TYPE_VIS_ONLY __forward_list_const_iterator { typedef _NodeConstPtr __node_const_pointer; __node_const_pointer __ptr_; _LIBCPP_INLINE_VISIBILITY explicit __forward_list_const_iterator(__node_const_pointer __p) _NOEXCEPT : __ptr_(__p) {} typedef typename remove_const < typename pointer_traits<__node_const_pointer>::element_type >::type __node; - typedef typename pointer_traits<__node_const_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind<__node> -#else - rebind<__node>::other -#endif - __node_pointer; + typedef typename __rebind_pointer<__node_const_pointer, __node>::type __node_pointer; template friend class forward_list; public: typedef forward_iterator_tag iterator_category; typedef typename __node::value_type value_type; typedef const value_type& reference; typedef typename pointer_traits<__node_const_pointer>::difference_type difference_type; - typedef typename pointer_traits<__node_const_pointer>::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer<__node_const_pointer, const value_type>::type pointer; _LIBCPP_INLINE_VISIBILITY __forward_list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} _LIBCPP_INLINE_VISIBILITY __forward_list_const_iterator(__forward_list_iterator<__node_pointer> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __ptr_->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__ptr_->__value_);} _LIBCPP_INLINE_VISIBILITY __forward_list_const_iterator& operator++() { __ptr_ = __ptr_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __forward_list_const_iterator operator++(int) { __forward_list_const_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) {return __x.__ptr_ == __y.__ptr_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) {return !(__x == __y);} }; template class __forward_list_base { protected: typedef _Tp value_type; typedef _Alloc allocator_type; typedef typename allocator_traits::void_pointer void_pointer; typedef __forward_list_node __node; typedef typename __begin_node_of::type __begin_node; typedef typename __rebind_alloc_helper, __node>::type __node_allocator; typedef allocator_traits<__node_allocator> __node_traits; typedef typename __node_traits::pointer __node_pointer; typedef typename __node_traits::pointer __node_const_pointer; typedef typename __rebind_alloc_helper, __begin_node>::type __begin_node_allocator; typedef typename allocator_traits<__begin_node_allocator>::pointer __begin_node_pointer; __compressed_pair<__begin_node, __node_allocator> __before_begin_; _LIBCPP_INLINE_VISIBILITY __node_pointer __before_begin() _NOEXCEPT {return static_cast<__node_pointer>(pointer_traits<__begin_node_pointer>:: pointer_to(__before_begin_.first()));} _LIBCPP_INLINE_VISIBILITY __node_const_pointer __before_begin() const _NOEXCEPT {return static_cast<__node_const_pointer>(pointer_traits<__begin_node_pointer>:: pointer_to(const_cast<__begin_node&>(__before_begin_.first())));} _LIBCPP_INLINE_VISIBILITY __node_allocator& __alloc() _NOEXCEPT {return __before_begin_.second();} _LIBCPP_INLINE_VISIBILITY const __node_allocator& __alloc() const _NOEXCEPT {return __before_begin_.second();} typedef __forward_list_iterator<__node_pointer> iterator; typedef __forward_list_const_iterator<__node_pointer> const_iterator; _LIBCPP_INLINE_VISIBILITY __forward_list_base() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) : __before_begin_(__begin_node()) {} _LIBCPP_INLINE_VISIBILITY __forward_list_base(const allocator_type& __a) : __before_begin_(__begin_node(), __node_allocator(__a)) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES public: __forward_list_base(__forward_list_base&& __x) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); __forward_list_base(__forward_list_base&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES private: __forward_list_base(const __forward_list_base&); __forward_list_base& operator=(const __forward_list_base&); public: ~__forward_list_base(); protected: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __forward_list_base& __x) {__copy_assign_alloc(__x, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x) _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<__node_allocator>::value) {__move_assign_alloc(__x, integral_constant());} public: void swap(__forward_list_base& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || __is_nothrow_swappable<__node_allocator>::value); #endif protected: void clear() _NOEXCEPT; private: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __forward_list_base&, false_type) {} _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __forward_list_base& __x, true_type) { if (__alloc() != __x.__alloc()) clear(); __alloc() = __x.__alloc(); } _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x, false_type) _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__alloc() = _VSTD::move(__x.__alloc());} }; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value) : __before_begin_(_VSTD::move(__x.__before_begin_)) { __x.__before_begin()->__next_ = nullptr; } template inline _LIBCPP_INLINE_VISIBILITY __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x, const allocator_type& __a) : __before_begin_(__begin_node(), __node_allocator(__a)) { if (__alloc() == __x.__alloc()) { __before_begin()->__next_ = __x.__before_begin()->__next_; __x.__before_begin()->__next_ = nullptr; } } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template __forward_list_base<_Tp, _Alloc>::~__forward_list_base() { clear(); } template inline _LIBCPP_INLINE_VISIBILITY void __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || __is_nothrow_swappable<__node_allocator>::value) #endif { __swap_allocator(__alloc(), __x.__alloc(), integral_constant()); using _VSTD::swap; swap(__before_begin()->__next_, __x.__before_begin()->__next_); } template void __forward_list_base<_Tp, _Alloc>::clear() _NOEXCEPT { __node_allocator& __a = __alloc(); for (__node_pointer __p = __before_begin()->__next_; __p != nullptr;) { __node_pointer __next = __p->__next_; __node_traits::destroy(__a, _VSTD::addressof(__p->__value_)); __node_traits::deallocate(__a, __p, 1); __p = __next; } __before_begin()->__next_ = nullptr; } template */> class _LIBCPP_TYPE_VIS_ONLY forward_list : private __forward_list_base<_Tp, _Alloc> { typedef __forward_list_base<_Tp, _Alloc> base; typedef typename base::__node_allocator __node_allocator; typedef typename base::__node __node; typedef typename base::__node_traits __node_traits; typedef typename base::__node_pointer __node_pointer; public: typedef _Tp value_type; typedef _Alloc allocator_type; static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; _LIBCPP_INLINE_VISIBILITY forward_list() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) {} // = default; explicit forward_list(const allocator_type& __a); explicit forward_list(size_type __n); #if _LIBCPP_STD_VER > 11 explicit forward_list(size_type __n, const allocator_type& __a); #endif forward_list(size_type __n, const value_type& __v); forward_list(size_type __n, const value_type& __v, const allocator_type& __a); template forward_list(_InputIterator __f, _InputIterator __l, typename enable_if< __is_input_iterator<_InputIterator>::value >::type* = nullptr); template forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a, typename enable_if< __is_input_iterator<_InputIterator>::value >::type* = nullptr); forward_list(const forward_list& __x); forward_list(const forward_list& __x, const allocator_type& __a); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY forward_list(forward_list&& __x) _NOEXCEPT_(is_nothrow_move_constructible::value) : base(_VSTD::move(__x)) {} forward_list(forward_list&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS forward_list(initializer_list __il); forward_list(initializer_list __il, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS // ~forward_list() = default; forward_list& operator=(const forward_list& __x); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES forward_list& operator=(forward_list&& __x) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value); #endif #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS forward_list& operator=(initializer_list __il); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template typename enable_if < __is_input_iterator<_InputIterator>::value, void >::type assign(_InputIterator __f, _InputIterator __l); void assign(size_type __n, const value_type& __v); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS void assign(initializer_list __il); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(base::__alloc());} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(base::__before_begin()->__next_);} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return const_iterator(base::__before_begin()->__next_);} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return iterator(nullptr);} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return const_iterator(nullptr);} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return const_iterator(base::__before_begin()->__next_);} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return const_iterator(nullptr);} _LIBCPP_INLINE_VISIBILITY iterator before_begin() _NOEXCEPT {return iterator(base::__before_begin());} _LIBCPP_INLINE_VISIBILITY const_iterator before_begin() const _NOEXCEPT {return const_iterator(base::__before_begin());} _LIBCPP_INLINE_VISIBILITY const_iterator cbefore_begin() const _NOEXCEPT {return const_iterator(base::__before_begin());} _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return base::__before_begin()->__next_ == nullptr;} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return numeric_limits::max();} _LIBCPP_INLINE_VISIBILITY reference front() {return base::__before_begin()->__next_->__value_;} _LIBCPP_INLINE_VISIBILITY const_reference front() const {return base::__before_begin()->__next_->__value_;} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template void emplace_front(_Args&&... __args); #endif void push_front(value_type&& __v); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void push_front(const value_type& __v); void pop_front(); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template iterator emplace_after(const_iterator __p, _Args&&... __args); #endif // _LIBCPP_HAS_NO_VARIADICS iterator insert_after(const_iterator __p, value_type&& __v); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES iterator insert_after(const_iterator __p, const value_type& __v); iterator insert_after(const_iterator __p, size_type __n, const value_type& __v); template _LIBCPP_INLINE_VISIBILITY typename enable_if < __is_input_iterator<_InputIterator>::value, iterator >::type insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS iterator insert_after(const_iterator __p, initializer_list __il) {return insert_after(__p, __il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS iterator erase_after(const_iterator __p); iterator erase_after(const_iterator __f, const_iterator __l); _LIBCPP_INLINE_VISIBILITY void swap(forward_list& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) #endif {base::swap(__x);} void resize(size_type __n); void resize(size_type __n, const value_type& __v); _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {base::clear();} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void splice_after(const_iterator __p, forward_list&& __x); _LIBCPP_INLINE_VISIBILITY void splice_after(const_iterator __p, forward_list&& __x, const_iterator __i); _LIBCPP_INLINE_VISIBILITY void splice_after(const_iterator __p, forward_list&& __x, const_iterator __f, const_iterator __l); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void splice_after(const_iterator __p, forward_list& __x); void splice_after(const_iterator __p, forward_list& __x, const_iterator __i); void splice_after(const_iterator __p, forward_list& __x, const_iterator __f, const_iterator __l); void remove(const value_type& __v); template void remove_if(_Predicate __pred); _LIBCPP_INLINE_VISIBILITY void unique() {unique(__equal_to());} template void unique(_BinaryPredicate __binary_pred); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void merge(forward_list&& __x) {merge(__x, __less());} template _LIBCPP_INLINE_VISIBILITY void merge(forward_list&& __x, _Compare __comp) {merge(__x, _VSTD::move(__comp));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void merge(forward_list& __x) {merge(__x, __less());} template void merge(forward_list& __x, _Compare __comp); _LIBCPP_INLINE_VISIBILITY void sort() {sort(__less());} template void sort(_Compare __comp); void reverse() _NOEXCEPT; private: #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES void __move_assign(forward_list& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); void __move_assign(forward_list& __x, false_type); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template static __node_pointer __merge(__node_pointer __f1, __node_pointer __f2, _Compare& __comp); template static __node_pointer __sort(__node_pointer __f, difference_type __sz, _Compare& __comp); }; template inline _LIBCPP_INLINE_VISIBILITY forward_list<_Tp, _Alloc>::forward_list(const allocator_type& __a) : base(__a) { } template forward_list<_Tp, _Alloc>::forward_list(size_type __n) { if (__n > 0) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1)); for (__node_pointer __p = base::__before_begin(); __n > 0; --__n, __p = __p->__next_) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_)); __h->__next_ = nullptr; __p->__next_ = __h.release(); } } } #if _LIBCPP_STD_VER > 11 template forward_list<_Tp, _Alloc>::forward_list(size_type __n, const allocator_type& __a) : base ( __a ) { if (__n > 0) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1)); for (__node_pointer __p = base::__before_begin(); __n > 0; --__n, __p = __p->__next_) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_)); __h->__next_ = nullptr; __p->__next_ = __h.release(); } } } #endif template forward_list<_Tp, _Alloc>::forward_list(size_type __n, const value_type& __v) { insert_after(cbefore_begin(), __n, __v); } template forward_list<_Tp, _Alloc>::forward_list(size_type __n, const value_type& __v, const allocator_type& __a) : base(__a) { insert_after(cbefore_begin(), __n, __v); } template template forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, typename enable_if< __is_input_iterator<_InputIterator>::value >::type*) { insert_after(cbefore_begin(), __f, __l); } template template forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a, typename enable_if< __is_input_iterator<_InputIterator>::value >::type*) : base(__a) { insert_after(cbefore_begin(), __f, __l); } template forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x) : base(allocator_type( __node_traits::select_on_container_copy_construction(__x.__alloc()) ) ) { insert_after(cbefore_begin(), __x.begin(), __x.end()); } template forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x, const allocator_type& __a) : base(__a) { insert_after(cbefore_begin(), __x.begin(), __x.end()); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template forward_list<_Tp, _Alloc>::forward_list(forward_list&& __x, const allocator_type& __a) : base(_VSTD::move(__x), __a) { if (base::__alloc() != __x.__alloc()) { typedef move_iterator _Ip; insert_after(cbefore_begin(), _Ip(__x.begin()), _Ip(__x.end())); } } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template forward_list<_Tp, _Alloc>::forward_list(initializer_list __il) { insert_after(cbefore_begin(), __il.begin(), __il.end()); } template forward_list<_Tp, _Alloc>::forward_list(initializer_list __il, const allocator_type& __a) : base(__a) { insert_after(cbefore_begin(), __il.begin(), __il.end()); } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(const forward_list& __x) { if (this != &__x) { base::__copy_assign_alloc(__x); assign(__x.begin(), __x.end()); } return *this; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { clear(); base::__move_assign_alloc(__x); base::__before_begin()->__next_ = __x.__before_begin()->__next_; __x.__before_begin()->__next_ = nullptr; } template void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, false_type) { if (base::__alloc() == __x.__alloc()) __move_assign(__x, true_type()); else { typedef move_iterator _Ip; assign(_Ip(__x.begin()), _Ip(__x.end())); } } template inline _LIBCPP_INLINE_VISIBILITY forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(forward_list&& __x) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value) { __move_assign(__x, integral_constant()); return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template inline _LIBCPP_INLINE_VISIBILITY forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(initializer_list __il) { assign(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template template typename enable_if < __is_input_iterator<_InputIterator>::value, void >::type forward_list<_Tp, _Alloc>::assign(_InputIterator __f, _InputIterator __l) { iterator __i = before_begin(); iterator __j = _VSTD::next(__i); iterator __e = end(); for (; __j != __e && __f != __l; ++__i, (void) ++__j, ++__f) *__j = *__f; if (__j == __e) insert_after(__i, __f, __l); else erase_after(__i, __e); } template void forward_list<_Tp, _Alloc>::assign(size_type __n, const value_type& __v) { iterator __i = before_begin(); iterator __j = _VSTD::next(__i); iterator __e = end(); for (; __j != __e && __n > 0; --__n, ++__i, ++__j) *__j = __v; if (__j == __e) insert_after(__i, __n, __v); else erase_after(__i, __e); } #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template inline _LIBCPP_INLINE_VISIBILITY void forward_list<_Tp, _Alloc>::assign(initializer_list __il) { assign(__il.begin(), __il.end()); } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template template void forward_list<_Tp, _Alloc>::emplace_front(_Args&&... __args) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); __h->__next_ = base::__before_begin()->__next_; base::__before_begin()->__next_ = __h.release(); } #endif // _LIBCPP_HAS_NO_VARIADICS template void forward_list<_Tp, _Alloc>::push_front(value_type&& __v) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::move(__v)); __h->__next_ = base::__before_begin()->__next_; base::__before_begin()->__next_ = __h.release(); } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void forward_list<_Tp, _Alloc>::push_front(const value_type& __v) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); __h->__next_ = base::__before_begin()->__next_; base::__before_begin()->__next_ = __h.release(); } template void forward_list<_Tp, _Alloc>::pop_front() { __node_allocator& __a = base::__alloc(); __node_pointer __p = base::__before_begin()->__next_; base::__before_begin()->__next_ = __p->__next_; __node_traits::destroy(__a, _VSTD::addressof(__p->__value_)); __node_traits::deallocate(__a, __p, 1); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::emplace_after(const_iterator __p, _Args&&... __args) { __node_pointer const __r = __p.__ptr_; __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); __h->__next_ = __r->__next_; __r->__next_ = __h.release(); return iterator(__r->__next_); } #endif // _LIBCPP_HAS_NO_VARIADICS template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, value_type&& __v) { __node_pointer const __r = __p.__ptr_; __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::move(__v)); __h->__next_ = __r->__next_; __r->__next_ = __h.release(); return iterator(__r->__next_); } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, const value_type& __v) { __node_pointer const __r = __p.__ptr_; __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); __h->__next_ = __r->__next_; __r->__next_ = __h.release(); return iterator(__r->__next_); } template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, const value_type& __v) { __node_pointer __r = __p.__ptr_; if (__n > 0) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); __node_pointer __first = __h.release(); __node_pointer __last = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (--__n; __n != 0; --__n, __last = __last->__next_) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); __last->__next_ = __h.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (__first != nullptr) { __node_pointer __next = __first->__next_; __node_traits::destroy(__a, _VSTD::addressof(__first->__value_)); __node_traits::deallocate(__a, __first, 1); __first = __next; } throw; } #endif // _LIBCPP_NO_EXCEPTIONS __last->__next_ = __r->__next_; __r->__next_ = __first; __r = __last; } return iterator(__r); } template template typename enable_if < __is_input_iterator<_InputIterator>::value, typename forward_list<_Tp, _Alloc>::iterator >::type forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l) { __node_pointer __r = __p.__ptr_; if (__f != __l) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), *__f); __node_pointer __first = __h.release(); __node_pointer __last = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_))) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), *__f); __last->__next_ = __h.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (__first != nullptr) { __node_pointer __next = __first->__next_; __node_traits::destroy(__a, _VSTD::addressof(__first->__value_)); __node_traits::deallocate(__a, __first, 1); __first = __next; } throw; } #endif // _LIBCPP_NO_EXCEPTIONS __last->__next_ = __r->__next_; __r->__next_ = __first; __r = __last; } return iterator(__r); } template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::erase_after(const_iterator __f) { __node_pointer __p = __f.__ptr_; __node_pointer __n = __p->__next_; __p->__next_ = __n->__next_; __node_allocator& __a = base::__alloc(); __node_traits::destroy(__a, _VSTD::addressof(__n->__value_)); __node_traits::deallocate(__a, __n, 1); return iterator(__p->__next_); } template typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::erase_after(const_iterator __f, const_iterator __l) { __node_pointer __e = __l.__ptr_; if (__f != __l) { __node_pointer __p = __f.__ptr_; __node_pointer __n = __p->__next_; if (__n != __e) { __p->__next_ = __e; __node_allocator& __a = base::__alloc(); do { __p = __n->__next_; __node_traits::destroy(__a, _VSTD::addressof(__n->__value_)); __node_traits::deallocate(__a, __n, 1); __n = __p; } while (__n != __e); } } return iterator(__e); } template void forward_list<_Tp, _Alloc>::resize(size_type __n) { size_type __sz = 0; iterator __p = before_begin(); iterator __i = begin(); iterator __e = end(); for (; __i != __e && __sz < __n; ++__p, ++__i, ++__sz) ; if (__i != __e) erase_after(__p, __e); else { __n -= __sz; if (__n > 0) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1)); for (__node_pointer __ptr = __p.__ptr_; __n > 0; --__n, __ptr = __ptr->__next_) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_)); __h->__next_ = nullptr; __ptr->__next_ = __h.release(); } } } } template void forward_list<_Tp, _Alloc>::resize(size_type __n, const value_type& __v) { size_type __sz = 0; iterator __p = before_begin(); iterator __i = begin(); iterator __e = end(); for (; __i != __e && __sz < __n; ++__p, ++__i, ++__sz) ; if (__i != __e) erase_after(__p, __e); else { __n -= __sz; if (__n > 0) { __node_allocator& __a = base::__alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __h(nullptr, _Dp(__a, 1)); for (__node_pointer __ptr = __p.__ptr_; __n > 0; --__n, __ptr = __ptr->__next_) { __h.reset(__node_traits::allocate(__a, 1)); __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); __h->__next_ = nullptr; __ptr->__next_ = __h.release(); } } } } template void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& __x) { if (!__x.empty()) { if (__p.__ptr_->__next_ != nullptr) { const_iterator __lm1 = __x.before_begin(); while (__lm1.__ptr_->__next_ != nullptr) ++__lm1; __lm1.__ptr_->__next_ = __p.__ptr_->__next_; } __p.__ptr_->__next_ = __x.__before_begin()->__next_; __x.__before_begin()->__next_ = nullptr; } } template void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& __x, const_iterator __i) { const_iterator __lm1 = _VSTD::next(__i); if (__p != __i && __p != __lm1) { __i.__ptr_->__next_ = __lm1.__ptr_->__next_; __lm1.__ptr_->__next_ = __p.__ptr_->__next_; __p.__ptr_->__next_ = __lm1.__ptr_; } } template void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list& __x, const_iterator __f, const_iterator __l) { if (__f != __l && __p != __f) { const_iterator __lm1 = __f; while (__lm1.__ptr_->__next_ != __l.__ptr_) ++__lm1; if (__f != __lm1) { __lm1.__ptr_->__next_ = __p.__ptr_->__next_; __p.__ptr_->__next_ = __f.__ptr_->__next_; __f.__ptr_->__next_ = __l.__ptr_; } } } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list&& __x) { splice_after(__p, __x); } template inline _LIBCPP_INLINE_VISIBILITY void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list&& __x, const_iterator __i) { splice_after(__p, __x, __i); } template inline _LIBCPP_INLINE_VISIBILITY void forward_list<_Tp, _Alloc>::splice_after(const_iterator __p, forward_list&& __x, const_iterator __f, const_iterator __l) { splice_after(__p, __x, __f, __l); } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void forward_list<_Tp, _Alloc>::remove(const value_type& __v) { forward_list<_Tp, _Alloc> __deleted_nodes; // collect the nodes we're removing iterator __e = end(); for (iterator __i = before_begin(); __i.__ptr_->__next_ != nullptr;) { if (__i.__ptr_->__next_->__value_ == __v) { iterator __j = _VSTD::next(__i, 2); for (; __j != __e && *__j == __v; ++__j) ; __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j); if (__j == __e) break; __i = __j; } else ++__i; } } template template void forward_list<_Tp, _Alloc>::remove_if(_Predicate __pred) { iterator __e = end(); for (iterator __i = before_begin(); __i.__ptr_->__next_ != nullptr;) { if (__pred(__i.__ptr_->__next_->__value_)) { iterator __j = _VSTD::next(__i, 2); for (; __j != __e && __pred(*__j); ++__j) ; erase_after(__i, __j); if (__j == __e) break; __i = __j; } else ++__i; } } template template void forward_list<_Tp, _Alloc>::unique(_BinaryPredicate __binary_pred) { for (iterator __i = begin(), __e = end(); __i != __e;) { iterator __j = _VSTD::next(__i); for (; __j != __e && __binary_pred(*__i, *__j); ++__j) ; if (__i.__ptr_->__next_ != __j.__ptr_) erase_after(__i, __j); __i = __j; } } template template void forward_list<_Tp, _Alloc>::merge(forward_list& __x, _Compare __comp) { if (this != &__x) { base::__before_begin()->__next_ = __merge(base::__before_begin()->__next_, __x.__before_begin()->__next_, __comp); __x.__before_begin()->__next_ = nullptr; } } template template typename forward_list<_Tp, _Alloc>::__node_pointer forward_list<_Tp, _Alloc>::__merge(__node_pointer __f1, __node_pointer __f2, _Compare& __comp) { if (__f1 == nullptr) return __f2; if (__f2 == nullptr) return __f1; __node_pointer __r; if (__comp(__f2->__value_, __f1->__value_)) { __node_pointer __t = __f2; while (__t->__next_ != nullptr && __comp(__t->__next_->__value_, __f1->__value_)) __t = __t->__next_; __r = __f2; __f2 = __t->__next_; __t->__next_ = __f1; } else __r = __f1; __node_pointer __p = __f1; __f1 = __f1->__next_; while (__f1 != nullptr && __f2 != nullptr) { if (__comp(__f2->__value_, __f1->__value_)) { __node_pointer __t = __f2; while (__t->__next_ != nullptr && __comp(__t->__next_->__value_, __f1->__value_)) __t = __t->__next_; __p->__next_ = __f2; __f2 = __t->__next_; __t->__next_ = __f1; } __p = __f1; __f1 = __f1->__next_; } if (__f2 != nullptr) __p->__next_ = __f2; return __r; } template template inline _LIBCPP_INLINE_VISIBILITY void forward_list<_Tp, _Alloc>::sort(_Compare __comp) { base::__before_begin()->__next_ = __sort(base::__before_begin()->__next_, _VSTD::distance(begin(), end()), __comp); } template template typename forward_list<_Tp, _Alloc>::__node_pointer forward_list<_Tp, _Alloc>::__sort(__node_pointer __f1, difference_type __sz, _Compare& __comp) { switch (__sz) { case 0: case 1: return __f1; case 2: if (__comp(__f1->__next_->__value_, __f1->__value_)) { __node_pointer __t = __f1->__next_; __t->__next_ = __f1; __f1->__next_ = nullptr; __f1 = __t; } return __f1; } difference_type __sz1 = __sz / 2; difference_type __sz2 = __sz - __sz1; __node_pointer __t = _VSTD::next(iterator(__f1), __sz1 - 1).__ptr_; __node_pointer __f2 = __t->__next_; __t->__next_ = nullptr; return __merge(__sort(__f1, __sz1, __comp), __sort(__f2, __sz2, __comp), __comp); } template void forward_list<_Tp, _Alloc>::reverse() _NOEXCEPT { __node_pointer __p = base::__before_begin()->__next_; if (__p != nullptr) { __node_pointer __f = __p->__next_; __p->__next_ = nullptr; while (__f != nullptr) { __node_pointer __t = __f->__next_; __f->__next_ = __p; __p = __f; __f = __t; } base::__before_begin()->__next_ = __p; } } template bool operator==(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { typedef forward_list<_Tp, _Alloc> _Cp; typedef typename _Cp::const_iterator _Ip; _Ip __ix = __x.begin(); _Ip __ex = __x.end(); _Ip __iy = __y.begin(); _Ip __ey = __y.end(); for (; __ix != __ex && __iy != __ey; ++__ix, ++__iy) if (!(*__ix == *__iy)) return false; return (__ix == __ex) == (__iy == __ey); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const forward_list<_Tp, _Alloc>& __x, const forward_list<_Tp, _Alloc>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY void swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_FORWARD_LIST diff --git a/include/list b/include/list index 28d505582c0d..44b20e2fa28c 100644 --- a/include/list +++ b/include/list @@ -1,2329 +1,2389 @@ // -*- C++ -*- //===---------------------------- list ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_LIST #define _LIBCPP_LIST /* list synopsis namespace std { template > class list { public: // types: typedef T value_type; typedef Alloc allocator_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef implementation-defined size_type; typedef implementation-defined difference_type; typedef reverse_iterator reverse_iterator; typedef reverse_iterator const_reverse_iterator; list() noexcept(is_nothrow_default_constructible::value); explicit list(const allocator_type& a); explicit list(size_type n); explicit list(size_type n, const allocator_type& a); // C++14 list(size_type n, const value_type& value); list(size_type n, const value_type& value, const allocator_type& a); template list(Iter first, Iter last); template list(Iter first, Iter last, const allocator_type& a); list(const list& x); list(const list&, const allocator_type& a); list(list&& x) noexcept(is_nothrow_move_constructible::value); list(list&&, const allocator_type& a); list(initializer_list); list(initializer_list, const allocator_type& a); ~list(); list& operator=(const list& x); list& operator=(list&& x) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value); list& operator=(initializer_list); template void assign(Iter first, Iter last); void assign(size_type n, const value_type& t); void assign(initializer_list); 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; reference front(); const_reference front() const; reference back(); const_reference back() const; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; template void emplace_front(Args&&... args); void pop_front(); template void emplace_back(Args&&... args); void pop_back(); void push_front(const value_type& x); void push_front(value_type&& x); void push_back(const value_type& x); void push_back(value_type&& x); template iterator emplace(const_iterator position, Args&&... args); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); iterator insert(const_iterator position, size_type n, const value_type& x); template iterator insert(const_iterator position, Iter first, Iter last); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); iterator erase(const_iterator position, const_iterator last); void resize(size_type sz); void resize(size_type sz, const value_type& c); void swap(list&) noexcept(allocator_traits::is_always_equal::value); // C++17 void clear() noexcept; void splice(const_iterator position, list& x); void splice(const_iterator position, list&& x); void splice(const_iterator position, list& x, const_iterator i); void splice(const_iterator position, list&& x, const_iterator i); void splice(const_iterator position, list& x, const_iterator first, const_iterator last); void splice(const_iterator position, list&& x, const_iterator first, const_iterator last); void remove(const value_type& value); template void remove_if(Pred pred); void unique(); template void unique(BinaryPredicate binary_pred); void merge(list& x); void merge(list&& x); template void merge(list& x, Compare comp); template void merge(list&& x, Compare comp); void sort(); template void sort(Compare comp); void reverse() noexcept; }; template bool operator==(const list& x, const list& y); template bool operator< (const list& x, const list& y); template bool operator!=(const list& x, const list& y); template bool operator> (const list& x, const list& y); template bool operator>=(const list& x, const list& y); template bool operator<=(const list& x, const list& y); template void swap(list& x, list& y) noexcept(noexcept(x.swap(y))); } // std */ #include <__config> #include #include #include #include #include +#include #include <__undef_min_max> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template struct __list_node; +template struct __list_node_base; + +template +struct __list_node_pointer_traits { + typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type + __node_pointer; + typedef typename __rebind_pointer<_VoidPtr, __list_node_base<_Tp, _VoidPtr> >::type + __base_pointer; + +#if defined(_LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB) + typedef __base_pointer __link_pointer; +#else + typedef typename conditional< + is_pointer<_VoidPtr>::value, + __base_pointer, + __node_pointer + >::type __link_pointer; +#endif + + typedef typename conditional< + is_same<__link_pointer, __node_pointer>::value, + __base_pointer, + __node_pointer + >::type __non_link_pointer; + + static _LIBCPP_INLINE_VISIBILITY + __link_pointer __unsafe_link_pointer_cast(__link_pointer __p) { + return __p; + } + + static _LIBCPP_INLINE_VISIBILITY + __link_pointer __unsafe_link_pointer_cast(__non_link_pointer __p) { + return static_cast<__link_pointer>(static_cast<_VoidPtr>(__p)); + } + +}; template struct __list_node_base { - typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type - pointer; - typedef typename __rebind_pointer<_VoidPtr, __list_node_base>::type - __base_pointer; + typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits; + typedef typename _NodeTraits::__node_pointer __node_pointer; + typedef typename _NodeTraits::__base_pointer __base_pointer; + typedef typename _NodeTraits::__link_pointer __link_pointer; - pointer __prev_; - pointer __next_; + __link_pointer __prev_; + __link_pointer __next_; _LIBCPP_INLINE_VISIBILITY - __list_node_base() : __prev_(__self()), __next_(__self()) {} + __list_node_base() : __prev_(_NodeTraits::__unsafe_link_pointer_cast(__self())), + __next_(_NodeTraits::__unsafe_link_pointer_cast(__self())) {} _LIBCPP_INLINE_VISIBILITY - pointer __self() - { - return static_cast(pointer_traits<__base_pointer>::pointer_to(*this)); + __base_pointer __self() { + return pointer_traits<__base_pointer>::pointer_to(*this); + } + + _LIBCPP_INLINE_VISIBILITY + __node_pointer __as_node() { + return static_cast<__node_pointer>(__self()); } }; template struct __list_node : public __list_node_base<_Tp, _VoidPtr> { _Tp __value_; + + typedef __list_node_base<_Tp, _VoidPtr> __base; + typedef typename __base::__link_pointer __link_pointer; + + _LIBCPP_INLINE_VISIBILITY + __link_pointer __as_link() { + return static_cast<__link_pointer>(__base::__self()); + } }; template > class _LIBCPP_TYPE_VIS_ONLY list; template class __list_imp; template class _LIBCPP_TYPE_VIS_ONLY __list_const_iterator; template class _LIBCPP_TYPE_VIS_ONLY __list_iterator { - typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type - __node_pointer; + typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits; + typedef typename _NodeTraits::__link_pointer __link_pointer; - __node_pointer __ptr_; + __link_pointer __ptr_; #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY - explicit __list_iterator(__node_pointer __p, const void* __c) _NOEXCEPT + explicit __list_iterator(__link_pointer __p, const void* __c) _NOEXCEPT : __ptr_(__p) { __get_db()->__insert_ic(this, __c); } #else _LIBCPP_INLINE_VISIBILITY - explicit __list_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} + explicit __list_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) {} #endif template friend class list; template friend class __list_imp; template friend class __list_const_iterator; public: typedef bidirectional_iterator_tag iterator_category; typedef _Tp value_type; typedef value_type& reference; typedef typename __rebind_pointer<_VoidPtr, value_type>::type pointer; typedef typename pointer_traits::difference_type difference_type; _LIBCPP_INLINE_VISIBILITY __list_iterator() _NOEXCEPT : __ptr_(nullptr) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __list_iterator(const __list_iterator& __p) : __ptr_(__p.__ptr_) { __get_db()->__iterator_copy(this, &__p); } _LIBCPP_INLINE_VISIBILITY ~__list_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __list_iterator& operator=(const __list_iterator& __p) { if (this != &__p) { __get_db()->__iterator_copy(this, &__p); __ptr_ = __p.__ptr_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable list::iterator"); #endif - return __ptr_->__value_; + return __ptr_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable list::iterator"); #endif - return pointer_traits::pointer_to(__ptr_->__value_); + return pointer_traits::pointer_to(__ptr_->__as_node()->__value_); } _LIBCPP_INLINE_VISIBILITY __list_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable list::iterator"); #endif __ptr_ = __ptr_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __list_iterator operator++(int) {__list_iterator __t(*this); ++(*this); return __t;} _LIBCPP_INLINE_VISIBILITY __list_iterator& operator--() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), "Attempted to decrement non-decrementable list::iterator"); #endif __ptr_ = __ptr_->__prev_; return *this; } _LIBCPP_INLINE_VISIBILITY __list_iterator operator--(int) {__list_iterator __t(*this); --(*this); return __t;} friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __list_iterator& __x, const __list_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __list_iterator& __x, const __list_iterator& __y) {return !(__x == __y);} }; template class _LIBCPP_TYPE_VIS_ONLY __list_const_iterator { - typedef typename __rebind_pointer<_VoidPtr, __list_node<_Tp, _VoidPtr> >::type - __node_pointer; + typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits; + typedef typename _NodeTraits::__link_pointer __link_pointer; - __node_pointer __ptr_; + __link_pointer __ptr_; #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY - explicit __list_const_iterator(__node_pointer __p, const void* __c) _NOEXCEPT + explicit __list_const_iterator(__link_pointer __p, const void* __c) _NOEXCEPT : __ptr_(__p) { __get_db()->__insert_ic(this, __c); } #else _LIBCPP_INLINE_VISIBILITY - explicit __list_const_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} + explicit __list_const_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) {} #endif template friend class list; template friend class __list_imp; public: typedef bidirectional_iterator_tag iterator_category; typedef _Tp value_type; typedef const value_type& reference; typedef typename __rebind_pointer<_VoidPtr, const value_type>::type pointer; typedef typename pointer_traits::difference_type difference_type; _LIBCPP_INLINE_VISIBILITY __list_const_iterator() _NOEXCEPT : __ptr_(nullptr) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_i(this); #endif } _LIBCPP_INLINE_VISIBILITY __list_const_iterator(const __list_iterator<_Tp, _VoidPtr>& __p) _NOEXCEPT : __ptr_(__p.__ptr_) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__iterator_copy(this, &__p); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __list_const_iterator(const __list_const_iterator& __p) : __ptr_(__p.__ptr_) { __get_db()->__iterator_copy(this, &__p); } _LIBCPP_INLINE_VISIBILITY ~__list_const_iterator() { __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY __list_const_iterator& operator=(const __list_const_iterator& __p) { if (this != &__p) { __get_db()->__iterator_copy(this, &__p); __ptr_ = __p.__ptr_; } return *this; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reference operator*() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable list::const_iterator"); #endif - return __ptr_->__value_; + return __ptr_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to dereference a non-dereferenceable list::iterator"); #endif - return pointer_traits::pointer_to(__ptr_->__value_); + return pointer_traits::pointer_to(__ptr_->__as_node()->__value_); } _LIBCPP_INLINE_VISIBILITY __list_const_iterator& operator++() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment non-incrementable list::const_iterator"); #endif __ptr_ = __ptr_->__next_; return *this; } _LIBCPP_INLINE_VISIBILITY __list_const_iterator operator++(int) {__list_const_iterator __t(*this); ++(*this); return __t;} _LIBCPP_INLINE_VISIBILITY __list_const_iterator& operator--() { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), "Attempted to decrement non-decrementable list::const_iterator"); #endif __ptr_ = __ptr_->__prev_; return *this; } _LIBCPP_INLINE_VISIBILITY __list_const_iterator operator--(int) {__list_const_iterator __t(*this); --(*this); return __t;} friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __list_const_iterator& __x, const __list_const_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __list_const_iterator& __x, const __list_const_iterator& __y) {return !(__x == __y);} }; template class __list_imp { __list_imp(const __list_imp&); __list_imp& operator=(const __list_imp&); protected: typedef _Tp value_type; typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::void_pointer __void_pointer; typedef __list_iterator iterator; typedef __list_const_iterator const_iterator; typedef __list_node_base __node_base; typedef __list_node __node; typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; typedef allocator_traits<__node_allocator> __node_alloc_traits; typedef typename __node_alloc_traits::pointer __node_pointer; typedef typename __node_alloc_traits::pointer __node_const_pointer; + typedef __list_node_pointer_traits __node_pointer_traits; + typedef typename __node_pointer_traits::__link_pointer __link_pointer; + typedef __link_pointer __link_const_pointer; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::difference_type difference_type; typedef typename __rebind_alloc_helper<__alloc_traits, __node_base>::type __node_base_allocator; typedef typename allocator_traits<__node_base_allocator>::pointer __node_base_pointer; __node_base __end_; __compressed_pair __size_alloc_; + _LIBCPP_INLINE_VISIBILITY + __link_pointer __end_as_link() const _NOEXCEPT { + return __node_pointer_traits::__unsafe_link_pointer_cast( + const_cast<__node_base&>(__end_).__self()); + } + _LIBCPP_INLINE_VISIBILITY size_type& __sz() _NOEXCEPT {return __size_alloc_.first();} _LIBCPP_INLINE_VISIBILITY const size_type& __sz() const _NOEXCEPT {return __size_alloc_.first();} _LIBCPP_INLINE_VISIBILITY __node_allocator& __node_alloc() _NOEXCEPT {return __size_alloc_.second();} _LIBCPP_INLINE_VISIBILITY const __node_allocator& __node_alloc() const _NOEXCEPT {return __size_alloc_.second();} - static void __unlink_nodes(__node_pointer __f, __node_pointer __l) _NOEXCEPT; + static void __unlink_nodes(__link_pointer __f, __link_pointer __l) _NOEXCEPT; __list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value); __list_imp(const allocator_type& __a); ~__list_imp(); void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __sz() == 0;} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__end_.__next_, this); #else return iterator(__end_.__next_); #endif } _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 return const_iterator(__end_.__next_, this); #else return const_iterator(__end_.__next_); #endif } _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__end_)), this); + return iterator(__end_as_link(), this); #else - return iterator(static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__end_))); + return iterator(__end_as_link()); #endif } _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT { #if _LIBCPP_DEBUG_LEVEL >= 2 - return const_iterator(static_cast<__node_const_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(const_cast<__node_base&>(__end_))), this); + return const_iterator(__end_as_link(), this); #else - return const_iterator(static_cast<__node_const_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(const_cast<__node_base&>(__end_)))); + return const_iterator(__end_as_link()); #endif } void swap(__list_imp& __c) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __list_imp& __c) {__copy_assign_alloc(__c, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__list_imp& __c) _NOEXCEPT_( !__node_alloc_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<__node_allocator>::value) {__move_assign_alloc(__c, integral_constant());} private: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __list_imp& __c, true_type) { if (__node_alloc() != __c.__node_alloc()) clear(); __node_alloc() = __c.__node_alloc(); } _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __list_imp& __c, false_type) {} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__list_imp& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { __node_alloc() = _VSTD::move(__c.__node_alloc()); } _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__list_imp& __c, false_type) _NOEXCEPT {} }; // Unlink nodes [__f, __l] template inline _LIBCPP_INLINE_VISIBILITY void -__list_imp<_Tp, _Alloc>::__unlink_nodes(__node_pointer __f, __node_pointer __l) +__list_imp<_Tp, _Alloc>::__unlink_nodes(__link_pointer __f, __link_pointer __l) _NOEXCEPT { __f->__prev_->__next_ = __l->__next_; __l->__next_->__prev_ = __f->__prev_; } template inline _LIBCPP_INLINE_VISIBILITY __list_imp<_Tp, _Alloc>::__list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) : __size_alloc_(0) { } template inline _LIBCPP_INLINE_VISIBILITY __list_imp<_Tp, _Alloc>::__list_imp(const allocator_type& __a) : __size_alloc_(0, __node_allocator(__a)) { } template __list_imp<_Tp, _Alloc>::~__list_imp() { clear(); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__erase_c(this); #endif } template void __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT { if (!empty()) { __node_allocator& __na = __node_alloc(); - __node_pointer __f = __end_.__next_; - __node_pointer __l = static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__end_)); + __link_pointer __f = __end_.__next_; + __link_pointer __l = __end_as_link(); __unlink_nodes(__f, __l->__prev_); __sz() = 0; while (__f != __l) { - __node_pointer __n = __f; + __node_pointer __np = __f->__as_node(); __f = __f->__next_; - __node_alloc_traits::destroy(__na, _VSTD::addressof(__n->__value_)); - __node_alloc_traits::deallocate(__na, __n, 1); + __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); + __node_alloc_traits::deallocate(__na, __np, 1); } #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; const_iterator* __i = static_cast((*__p)->__i_); if (__i->__ptr_ != __l) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif } } template void __list_imp<_Tp, _Alloc>::swap(__list_imp& __c) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value) #endif { _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value || this->__node_alloc() == __c.__node_alloc(), "list::swap: Either propagate_on_container_swap must be true" " or the allocators must compare equal"); using _VSTD::swap; __swap_allocator(__node_alloc(), __c.__node_alloc()); swap(__sz(), __c.__sz()); swap(__end_, __c.__end_); if (__sz() == 0) - __end_.__next_ = __end_.__prev_ = __end_.__self(); + __end_.__next_ = __end_.__prev_ = __end_as_link(); else - __end_.__prev_->__next_ = __end_.__next_->__prev_ = __end_.__self(); + __end_.__prev_->__next_ = __end_.__next_->__prev_ = __end_as_link(); if (__c.__sz() == 0) - __c.__end_.__next_ = __c.__end_.__prev_ = __c.__end_.__self(); + __c.__end_.__next_ = __c.__end_.__prev_ = __c.__end_as_link(); else - __c.__end_.__prev_->__next_ = __c.__end_.__next_->__prev_ = __c.__end_.__self(); + __c.__end_.__prev_->__next_ = __c.__end_.__next_->__prev_ = __c.__end_as_link(); #if _LIBCPP_DEBUG_LEVEL >= 2 __libcpp_db* __db = __get_db(); __c_node* __cn1 = __db->__find_c_and_lock(this); __c_node* __cn2 = __db->__find_c(&__c); std::swap(__cn1->beg_, __cn2->beg_); std::swap(__cn1->end_, __cn2->end_); std::swap(__cn1->cap_, __cn2->cap_); for (__i_node** __p = __cn1->end_; __p != __cn1->beg_;) { --__p; const_iterator* __i = static_cast((*__p)->__i_); - if (__i->__ptr_ == static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__c.__end_))) + if (__i->__ptr_ == __c.__end_as_link()) { __cn2->__add(*__p); if (--__cn1->end_ != __p) memmove(__p, __p+1, (__cn1->end_ - __p)*sizeof(__i_node*)); } else (*__p)->__c_ = __cn1; } for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) { --__p; const_iterator* __i = static_cast((*__p)->__i_); - if (__i->__ptr_ == static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__end_))) + if (__i->__ptr_ == __end_as_link()) { __cn1->__add(*__p); if (--__cn2->end_ != __p) memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); } else (*__p)->__c_ = __cn2; } __db->unlock(); #endif } template */> class _LIBCPP_TYPE_VIS_ONLY list : private __list_imp<_Tp, _Alloc> { typedef __list_imp<_Tp, _Alloc> base; typedef typename base::__node __node; typedef typename base::__node_allocator __node_allocator; typedef typename base::__node_pointer __node_pointer; typedef typename base::__node_alloc_traits __node_alloc_traits; typedef typename base::__node_base __node_base; typedef typename base::__node_base_pointer __node_base_pointer; + typedef typename base::__link_pointer __link_pointer; public: typedef _Tp value_type; typedef _Alloc allocator_type; static_assert((is_same::value), "Invalid allocator::value_type"); typedef value_type& reference; typedef const value_type& const_reference; typedef typename base::pointer pointer; typedef typename base::const_pointer const_pointer; typedef typename base::size_type size_type; typedef typename base::difference_type difference_type; typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; _LIBCPP_INLINE_VISIBILITY list() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } _LIBCPP_INLINE_VISIBILITY explicit list(const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } explicit list(size_type __n); #if _LIBCPP_STD_VER > 11 explicit list(size_type __n, const allocator_type& __a); #endif list(size_type __n, const value_type& __x); list(size_type __n, const value_type& __x, const allocator_type& __a); template list(_InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type* = 0); template list(_InpIter __f, _InpIter __l, const allocator_type& __a, typename enable_if<__is_input_iterator<_InpIter>::value>::type* = 0); list(const list& __c); list(const list& __c, const allocator_type& __a); list& operator=(const list& __c); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS list(initializer_list __il); list(initializer_list __il, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES list(list&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); list(list&& __c, const allocator_type& __a); list& operator=(list&& __c) _NOEXCEPT_( __node_alloc_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY list& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template void assign(_InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type* = 0); void assign(size_type __n, const value_type& __x); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS allocator_type get_allocator() const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return base::__sz();} _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return base::empty();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return numeric_limits::max();} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return base::begin();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return base::begin();} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return base::end();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return base::end();} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return base::begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return base::end();} _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY reference front() { _LIBCPP_ASSERT(!empty(), "list::front called on empty list"); - return base::__end_.__next_->__value_; + return base::__end_.__next_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY const_reference front() const { _LIBCPP_ASSERT(!empty(), "list::front called on empty list"); - return base::__end_.__next_->__value_; + return base::__end_.__next_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY reference back() { _LIBCPP_ASSERT(!empty(), "list::back called on empty list"); - return base::__end_.__prev_->__value_; + return base::__end_.__prev_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY const_reference back() const { _LIBCPP_ASSERT(!empty(), "list::back called on empty list"); - return base::__end_.__prev_->__value_; + return base::__end_.__prev_->__as_node()->__value_; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES void push_front(value_type&& __x); void push_back(value_type&& __x); #ifndef _LIBCPP_HAS_NO_VARIADICS template void emplace_front(_Args&&... __args); template void emplace_back(_Args&&... __args); template iterator emplace(const_iterator __p, _Args&&... __args); #endif // _LIBCPP_HAS_NO_VARIADICS iterator insert(const_iterator __p, value_type&& __x); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void push_front(const value_type& __x); void push_back(const value_type& __x); iterator insert(const_iterator __p, const value_type& __x); iterator insert(const_iterator __p, size_type __n, const value_type& __x); template iterator insert(const_iterator __p, _InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type* = 0); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, initializer_list __il) {return insert(__p, __il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void swap(list& __c) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value) #endif {base::swap(__c);} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {base::clear();} void pop_front(); void pop_back(); iterator erase(const_iterator __p); iterator erase(const_iterator __f, const_iterator __l); void resize(size_type __n); void resize(size_type __n, const value_type& __x); void splice(const_iterator __p, list& __c); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void splice(const_iterator __p, list&& __c) {splice(__p, __c);} #endif void splice(const_iterator __p, list& __c, const_iterator __i); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void splice(const_iterator __p, list&& __c, const_iterator __i) {splice(__p, __c, __i);} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void splice(const_iterator __p, list&& __c, const_iterator __f, const_iterator __l) {splice(__p, __c, __f, __l);} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void remove(const value_type& __x); template void remove_if(_Pred __pred); void unique(); template void unique(_BinaryPred __binary_pred); void merge(list& __c); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void merge(list&& __c) {merge(__c);} #endif template void merge(list& __c, _Comp __comp); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template _LIBCPP_INLINE_VISIBILITY void merge(list&& __c, _Comp __comp) {merge(__c, __comp);} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void sort(); template void sort(_Comp __comp); void reverse() _NOEXCEPT; bool __invariants() const; #if _LIBCPP_DEBUG_LEVEL >= 2 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_DEBUG_LEVEL >= 2 private: - static void __link_nodes (__node_pointer __p, __node_pointer __f, __node_pointer __l); - void __link_nodes_at_front(__node_pointer __f, __node_pointer __l); - void __link_nodes_at_back (__node_pointer __f, __node_pointer __l); + static void __link_nodes (__link_pointer __p, __link_pointer __f, __link_pointer __l); + void __link_nodes_at_front(__link_pointer __f, __link_pointer __l); + void __link_nodes_at_back (__link_pointer __f, __link_pointer __l); iterator __iterator(size_type __n); template static iterator __sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp); void __move_assign(list& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value); void __move_assign(list& __c, false_type); }; // Link in nodes [__f, __l] just prior to __p template inline _LIBCPP_INLINE_VISIBILITY void -list<_Tp, _Alloc>::__link_nodes(__node_pointer __p, __node_pointer __f, __node_pointer __l) +list<_Tp, _Alloc>::__link_nodes(__link_pointer __p, __link_pointer __f, __link_pointer __l) { __p->__prev_->__next_ = __f; __f->__prev_ = __p->__prev_; __p->__prev_ = __l; __l->__next_ = __p; } // Link in nodes [__f, __l] at the front of the list template inline _LIBCPP_INLINE_VISIBILITY void -list<_Tp, _Alloc>::__link_nodes_at_front(__node_pointer __f, __node_pointer __l) +list<_Tp, _Alloc>::__link_nodes_at_front(__link_pointer __f, __link_pointer __l) { - __f->__prev_ = base::__end_.__self(); + __f->__prev_ = base::__end_as_link(); __l->__next_ = base::__end_.__next_; __l->__next_->__prev_ = __l; base::__end_.__next_ = __f; } // Link in nodes [__f, __l] at the front of the list template inline _LIBCPP_INLINE_VISIBILITY void -list<_Tp, _Alloc>::__link_nodes_at_back(__node_pointer __f, __node_pointer __l) +list<_Tp, _Alloc>::__link_nodes_at_back(__link_pointer __f, __link_pointer __l) { - __l->__next_ = base::__end_.__self(); + __l->__next_ = base::__end_as_link(); __f->__prev_ = base::__end_.__prev_; __f->__prev_->__next_ = __f; base::__end_.__prev_ = __l; } template inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::__iterator(size_type __n) { return __n <= base::__sz() / 2 ? _VSTD::next(begin(), __n) : _VSTD::prev(end(), base::__sz() - __n); } template list<_Tp, _Alloc>::list(size_type __n) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __n > 0; --__n) #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES emplace_back(); #else push_back(value_type()); #endif } #if _LIBCPP_STD_VER > 11 template list<_Tp, _Alloc>::list(size_type __n, const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __n > 0; --__n) #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES emplace_back(); #else push_back(value_type()); #endif } #endif template list<_Tp, _Alloc>::list(size_type __n, const value_type& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __n > 0; --__n) push_back(__x); } template list<_Tp, _Alloc>::list(size_type __n, const value_type& __x, const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __n > 0; --__n) push_back(__x); } template template list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type*) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __f != __l; ++__f) push_back(*__f); } template template list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, const allocator_type& __a, typename enable_if<__is_input_iterator<_InpIter>::value>::type*) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (; __f != __l; ++__f) push_back(*__f); } template list<_Tp, _Alloc>::list(const list& __c) : base(allocator_type( __node_alloc_traits::select_on_container_copy_construction( __c.__node_alloc()))) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i) push_back(*__i); } template list<_Tp, _Alloc>::list(const list& __c, const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i) push_back(*__i); } #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template list<_Tp, _Alloc>::list(initializer_list __il, const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (typename initializer_list::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i) push_back(*__i); } template list<_Tp, _Alloc>::list(initializer_list __il) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif for (typename initializer_list::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i) push_back(*__i); } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template inline _LIBCPP_INLINE_VISIBILITY list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(const list& __c) { if (this != &__c) { base::__copy_assign_alloc(__c); assign(__c.begin(), __c.end()); } return *this; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY list<_Tp, _Alloc>::list(list&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value) : base(allocator_type(_VSTD::move(__c.__node_alloc()))) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif splice(end(), __c); } template inline _LIBCPP_INLINE_VISIBILITY list<_Tp, _Alloc>::list(list&& __c, const allocator_type& __a) : base(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif if (__a == __c.get_allocator()) splice(end(), __c); else { typedef move_iterator _Ip; assign(_Ip(__c.begin()), _Ip(__c.end())); } } template inline _LIBCPP_INLINE_VISIBILITY list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(list&& __c) _NOEXCEPT_( __node_alloc_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value) { __move_assign(__c, integral_constant()); return *this; } template void list<_Tp, _Alloc>::__move_assign(list& __c, false_type) { if (base::__node_alloc() != __c.__node_alloc()) { typedef move_iterator _Ip; assign(_Ip(__c.begin()), _Ip(__c.end())); } else __move_assign(__c, true_type()); } template void list<_Tp, _Alloc>::__move_assign(list& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { clear(); base::__move_assign_alloc(__c); splice(end(), __c); } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template template void list<_Tp, _Alloc>::assign(_InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type*) { iterator __i = begin(); iterator __e = end(); for (; __f != __l && __i != __e; ++__f, ++__i) *__i = *__f; if (__i == __e) insert(__e, __f, __l); else erase(__i, __e); } template void list<_Tp, _Alloc>::assign(size_type __n, const value_type& __x) { iterator __i = begin(); iterator __e = end(); for (; __n > 0 && __i != __e; --__n, ++__i) *__i = __x; if (__i == __e) insert(__e, __n, __x); else erase(__i, __e); } template inline _LIBCPP_INLINE_VISIBILITY _Alloc list<_Tp, _Alloc>::get_allocator() const _NOEXCEPT { return allocator_type(base::__node_alloc()); } template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, const value_type& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::insert(iterator, x) called with an iterator not" " referring to this list"); #endif __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); - __link_nodes(__p.__ptr_, __hold.get(), __hold.get()); + __link_nodes(__p.__ptr_, __hold->__as_link(), __hold->__as_link()); ++base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__hold.release(), this); + return iterator(__hold.release()->__as_link(), this); #else - return iterator(__hold.release()); + return iterator(__hold.release()->__as_link()); #endif } template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::insert(iterator, n, x) called with an iterator not" " referring to this list"); iterator __r(__p.__ptr_, this); #else iterator __r(__p.__ptr_); #endif if (__n > 0) { size_type __ds = 0; __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); ++__ds; #if _LIBCPP_DEBUG_LEVEL >= 2 - __r = iterator(__hold.get(), this); + __r = iterator(__hold->__as_link(), this); #else - __r = iterator(__hold.get()); + __r = iterator(__hold->__as_link()); #endif __hold.release(); iterator __e = __r; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (--__n; __n != 0; --__n, ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); - __e.__ptr_->__next_ = __hold.get(); + __e.__ptr_->__next_ = __hold->__as_link(); __hold->__prev_ = __e.__ptr_; __hold.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (true) { __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e)); - __node_pointer __prev = __e.__ptr_->__prev_; - __node_alloc_traits::deallocate(__na, __e.__ptr_, 1); + __link_pointer __prev = __e.__ptr_->__prev_; + __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; #if _LIBCPP_DEBUG_LEVEL >= 2 __e = iterator(__prev, this); #else __e = iterator(__prev); #endif } throw; } #endif // _LIBCPP_NO_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } return __r; } template template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, typename enable_if<__is_input_iterator<_InpIter>::value>::type*) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::insert(iterator, range) called with an iterator not" " referring to this list"); iterator __r(__p.__ptr_, this); #else iterator __r(__p.__ptr_); #endif if (__f != __l) { size_type __ds = 0; __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f); ++__ds; #if _LIBCPP_DEBUG_LEVEL >= 2 - __r = iterator(__hold.get(), this); + __r = iterator(__hold.get()->__as_link(), this); #else - __r = iterator(__hold.get()); + __r = iterator(__hold.get()->__as_link()); #endif __hold.release(); iterator __e = __r; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (++__f; __f != __l; ++__f, (void) ++__e, (void) ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f); - __e.__ptr_->__next_ = __hold.get(); + __e.__ptr_->__next_ = __hold.get()->__as_link(); __hold->__prev_ = __e.__ptr_; __hold.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (true) { __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e)); - __node_pointer __prev = __e.__ptr_->__prev_; - __node_alloc_traits::deallocate(__na, __e.__ptr_, 1); + __link_pointer __prev = __e.__ptr_->__prev_; + __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; #if _LIBCPP_DEBUG_LEVEL >= 2 __e = iterator(__prev, this); #else __e = iterator(__prev); #endif } throw; } #endif // _LIBCPP_NO_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } return __r; } template void list<_Tp, _Alloc>::push_front(const value_type& __x) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); - __link_nodes_at_front(__hold.get(), __hold.get()); + __link_pointer __nl = __hold->__as_link(); + __link_nodes_at_front(__nl, __nl); ++base::__sz(); __hold.release(); } template void list<_Tp, _Alloc>::push_back(const value_type& __x) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); - __link_nodes_at_back(__hold.get(), __hold.get()); + __link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link()); ++base::__sz(); __hold.release(); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template void list<_Tp, _Alloc>::push_front(value_type&& __x) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x)); - __link_nodes_at_front(__hold.get(), __hold.get()); + __link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link()); ++base::__sz(); __hold.release(); } template void list<_Tp, _Alloc>::push_back(value_type&& __x) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x)); - __link_nodes_at_back(__hold.get(), __hold.get()); + __link_nodes_at_back(__hold.get()->__as_link(), __hold.get()->__as_link()); ++base::__sz(); __hold.release(); } #ifndef _LIBCPP_HAS_NO_VARIADICS template template void list<_Tp, _Alloc>::emplace_front(_Args&&... __args) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...); - __link_nodes_at_front(__hold.get(), __hold.get()); + __link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link()); ++base::__sz(); __hold.release(); } template template void list<_Tp, _Alloc>::emplace_back(_Args&&... __args) { __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...); - __link_nodes_at_back(__hold.get(), __hold.get()); + __link_pointer __nl = __hold->__as_link(); + __link_nodes_at_back(__nl, __nl); ++base::__sz(); __hold.release(); } template template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::emplace(const_iterator __p, _Args&&... __args) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::emplace(iterator, args...) called with an iterator not" " referring to this list"); #endif __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...); - __link_nodes(__p.__ptr_, __hold.get(), __hold.get()); + __link_pointer __nl = __hold.get()->__as_link(); + __link_nodes(__p.__ptr_, __nl, __nl); ++base::__sz(); + __hold.release(); #if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__hold.release(), this); + return iterator(__nl, this); #else - return iterator(__hold.release()); + return iterator(__nl); #endif } #endif // _LIBCPP_HAS_NO_VARIADICS template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::insert(iterator, x) called with an iterator not" " referring to this list"); #endif __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x)); - __link_nodes(__p.__ptr_, __hold.get(), __hold.get()); + __link_pointer __nl = __hold->__as_link(); + __link_nodes(__p.__ptr_, __nl, __nl); ++base::__sz(); + __hold.release(); #if _LIBCPP_DEBUG_LEVEL >= 2 - return iterator(__hold.release(), this); + return iterator(__nl, this); #else - return iterator(__hold.release()); + return iterator(__nl); #endif } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void list<_Tp, _Alloc>::pop_front() { _LIBCPP_ASSERT(!empty(), "list::pop_front() called with empty list"); __node_allocator& __na = base::__node_alloc(); - __node_pointer __n = base::__end_.__next_; + __link_pointer __n = base::__end_.__next_; base::__unlink_nodes(__n, __n); --base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__ptr_ == __n) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif - __node_alloc_traits::destroy(__na, _VSTD::addressof(__n->__value_)); - __node_alloc_traits::deallocate(__na, __n, 1); + __node_pointer __np = __n->__as_node(); + __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); + __node_alloc_traits::deallocate(__na, __np, 1); } template void list<_Tp, _Alloc>::pop_back() { _LIBCPP_ASSERT(!empty(), "list::pop_back() called with empty list"); __node_allocator& __na = base::__node_alloc(); - __node_pointer __n = base::__end_.__prev_; + __link_pointer __n = base::__end_.__prev_; base::__unlink_nodes(__n, __n); --base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__ptr_ == __n) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif - __node_alloc_traits::destroy(__na, _VSTD::addressof(__n->__value_)); - __node_alloc_traits::deallocate(__na, __n, 1); + __node_pointer __np = __n->__as_node(); + __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); + __node_alloc_traits::deallocate(__na, __np, 1); } template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __p) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::erase(iterator) called with an iterator not" " referring to this list"); #endif _LIBCPP_ASSERT(__p != end(), "list::erase(iterator) called with a non-dereferenceable iterator"); __node_allocator& __na = base::__node_alloc(); - __node_pointer __n = __p.__ptr_; - __node_pointer __r = __n->__next_; + __link_pointer __n = __p.__ptr_; + __link_pointer __r = __n->__next_; base::__unlink_nodes(__n, __n); --base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__ptr_ == __n) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif - __node_alloc_traits::destroy(__na, _VSTD::addressof(__n->__value_)); - __node_alloc_traits::deallocate(__na, __n, 1); + __node_pointer __np = __n->__as_node(); + __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); + __node_alloc_traits::deallocate(__na, __np, 1); #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__r, this); #else return iterator(__r); #endif } template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __f, const_iterator __l) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__f) == this, "list::erase(iterator, iterator) called with an iterator not" " referring to this list"); #endif if (__f != __l) { __node_allocator& __na = base::__node_alloc(); base::__unlink_nodes(__f.__ptr_, __l.__ptr_->__prev_); while (__f != __l) { - __node_pointer __n = __f.__ptr_; + __link_pointer __n = __f.__ptr_; ++__f; --base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; iterator* __i = static_cast((*__p)->__i_); if (__i->__ptr_ == __n) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); #endif - __node_alloc_traits::destroy(__na, _VSTD::addressof(__n->__value_)); - __node_alloc_traits::deallocate(__na, __n, 1); + __node_pointer __np = __n->__as_node(); + __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); + __node_alloc_traits::deallocate(__na, __np, 1); } } #if _LIBCPP_DEBUG_LEVEL >= 2 return iterator(__l.__ptr_, this); #else return iterator(__l.__ptr_); #endif } template void list<_Tp, _Alloc>::resize(size_type __n) { if (__n < base::__sz()) erase(__iterator(__n), end()); else if (__n > base::__sz()) { __n -= base::__sz(); size_type __ds = 0; __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_)); ++__ds; #if _LIBCPP_DEBUG_LEVEL >= 2 - iterator __r = iterator(__hold.release(), this); + iterator __r = iterator(__hold.release()->__as_link(), this); #else - iterator __r = iterator(__hold.release()); + iterator __r = iterator(__hold.release()->__as_link()); #endif iterator __e = __r; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (--__n; __n != 0; --__n, ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_)); - __e.__ptr_->__next_ = __hold.get(); + __e.__ptr_->__next_ = __hold.get()->__as_link(); __hold->__prev_ = __e.__ptr_; __hold.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (true) { __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e)); - __node_pointer __prev = __e.__ptr_->__prev_; - __node_alloc_traits::deallocate(__na, __e.__ptr_, 1); + __link_pointer __prev = __e.__ptr_->__prev_; + __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; #if _LIBCPP_DEBUG_LEVEL >= 2 __e = iterator(__prev, this); #else __e = iterator(__prev); #endif } throw; } #endif // _LIBCPP_NO_EXCEPTIONS __link_nodes_at_back(__r.__ptr_, __e.__ptr_); base::__sz() += __ds; } } template void list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) { if (__n < base::__sz()) erase(__iterator(__n), end()); else if (__n > base::__sz()) { __n -= base::__sz(); size_type __ds = 0; __node_allocator& __na = base::__node_alloc(); typedef __allocator_destructor<__node_allocator> _Dp; unique_ptr<__node, _Dp> __hold(__node_alloc_traits::allocate(__na, 1), _Dp(__na, 1)); __hold->__prev_ = 0; __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); ++__ds; + __link_pointer __nl = __hold.release()->__as_link(); #if _LIBCPP_DEBUG_LEVEL >= 2 - iterator __r = iterator(__hold.release(), this); + iterator __r = iterator(__nl, this); #else - iterator __r = iterator(__hold.release()); + iterator __r = iterator(__nl); #endif iterator __e = __r; #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (--__n; __n != 0; --__n, ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); - __e.__ptr_->__next_ = __hold.get(); + __e.__ptr_->__next_ = __hold.get()->__as_link(); __hold->__prev_ = __e.__ptr_; __hold.release(); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { while (true) { __node_alloc_traits::destroy(__na, _VSTD::addressof(*__e)); - __node_pointer __prev = __e.__ptr_->__prev_; - __node_alloc_traits::deallocate(__na, __e.__ptr_, 1); + __link_pointer __prev = __e.__ptr_->__prev_; + __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; #if _LIBCPP_DEBUG_LEVEL >= 2 __e = iterator(__prev, this); #else __e = iterator(__prev); #endif } throw; } #endif // _LIBCPP_NO_EXCEPTIONS - __link_nodes(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>:: - pointer_to(base::__end_)), __r.__ptr_, __e.__ptr_); + __link_nodes(base::__end_as_link(), __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } } template void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c) { _LIBCPP_ASSERT(this != &__c, "list::splice(iterator, list) called with this == &list"); #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::splice(iterator, list) called with an iterator not" " referring to this list"); #endif if (!__c.empty()) { - __node_pointer __f = __c.__end_.__next_; - __node_pointer __l = __c.__end_.__prev_; + __link_pointer __f = __c.__end_.__next_; + __link_pointer __l = __c.__end_.__prev_; base::__unlink_nodes(__f, __l); __link_nodes(__p.__ptr_, __f, __l); base::__sz() += __c.__sz(); __c.__sz() = 0; #if _LIBCPP_DEBUG_LEVEL >= 2 __libcpp_db* __db = __get_db(); __c_node* __cn1 = __db->__find_c_and_lock(this); __c_node* __cn2 = __db->__find_c(&__c); for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) { --__p; iterator* __i = static_cast((*__p)->__i_); - if (__i->__ptr_ != static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__c.__end_))) + if (__i->__ptr_ != __c.__end_as_link()) { __cn1->__add(*__p); (*__p)->__c_ = __cn1; if (--__cn2->end_ != __p) memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); } } __db->unlock(); #endif } } template void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::splice(iterator, list, iterator) called with first iterator not" " referring to this list"); _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__i) == &__c, "list::splice(iterator, list, iterator) called with second iterator not" " referring to list argument"); _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(&__i), "list::splice(iterator, list, iterator) called with second iterator not" " derefereceable"); #endif if (__p.__ptr_ != __i.__ptr_ && __p.__ptr_ != __i.__ptr_->__next_) { - __node_pointer __f = __i.__ptr_; + __link_pointer __f = __i.__ptr_; base::__unlink_nodes(__f, __f); __link_nodes(__p.__ptr_, __f, __f); --__c.__sz(); ++base::__sz(); #if _LIBCPP_DEBUG_LEVEL >= 2 __libcpp_db* __db = __get_db(); __c_node* __cn1 = __db->__find_c_and_lock(this); __c_node* __cn2 = __db->__find_c(&__c); for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) { --__p; iterator* __j = static_cast((*__p)->__i_); if (__j->__ptr_ == __f) { __cn1->__add(*__p); (*__p)->__c_ = __cn1; if (--__cn2->end_ != __p) memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); } } __db->unlock(); #endif } } template void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "list::splice(iterator, list, iterator, iterator) called with first iterator not" " referring to this list"); _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__f) == &__c, "list::splice(iterator, list, iterator, iterator) called with second iterator not" " referring to list argument"); if (this == &__c) { for (const_iterator __i = __f; __i != __l; ++__i) _LIBCPP_ASSERT(__i != __p, "list::splice(iterator, list, iterator, iterator)" " called with the first iterator within the range" " of the second and third iterators"); } #endif if (__f != __l) { if (this != &__c) { size_type __s = _VSTD::distance(__f, __l); __c.__sz() -= __s; base::__sz() += __s; } - __node_pointer __first = __f.__ptr_; + __link_pointer __first = __f.__ptr_; --__l; - __node_pointer __last = __l.__ptr_; + __link_pointer __last = __l.__ptr_; base::__unlink_nodes(__first, __last); __link_nodes(__p.__ptr_, __first, __last); #if _LIBCPP_DEBUG_LEVEL >= 2 __libcpp_db* __db = __get_db(); __c_node* __cn1 = __db->__find_c_and_lock(this); __c_node* __cn2 = __db->__find_c(&__c); for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) { --__p; iterator* __j = static_cast((*__p)->__i_); - for (__node_pointer __k = __f.__ptr_; + for (__link_pointer __k = __f.__ptr_; __k != __l.__ptr_; __k = __k->__next_) { if (__j->__ptr_ == __k) { __cn1->__add(*__p); (*__p)->__c_ = __cn1; if (--__cn2->end_ != __p) memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); } } } __db->unlock(); #endif } } template void list<_Tp, _Alloc>::remove(const value_type& __x) { list<_Tp, _Alloc> __deleted_nodes; // collect the nodes we're removing for (const_iterator __i = begin(), __e = end(); __i != __e;) { if (*__i == __x) { const_iterator __j = _VSTD::next(__i); for (; __j != __e && *__j == __x; ++__j) ; __deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j); __i = __j; if (__i != __e) ++__i; } else ++__i; } } template template void list<_Tp, _Alloc>::remove_if(_Pred __pred) { for (iterator __i = begin(), __e = end(); __i != __e;) { if (__pred(*__i)) { iterator __j = _VSTD::next(__i); for (; __j != __e && __pred(*__j); ++__j) ; __i = erase(__i, __j); if (__i != __e) ++__i; } else ++__i; } } template inline _LIBCPP_INLINE_VISIBILITY void list<_Tp, _Alloc>::unique() { unique(__equal_to()); } template template void list<_Tp, _Alloc>::unique(_BinaryPred __binary_pred) { for (iterator __i = begin(), __e = end(); __i != __e;) { iterator __j = _VSTD::next(__i); for (; __j != __e && __binary_pred(*__i, *__j); ++__j) ; if (++__i != __j) __i = erase(__i, __j); } } template inline _LIBCPP_INLINE_VISIBILITY void list<_Tp, _Alloc>::merge(list& __c) { merge(__c, __less()); } template template void list<_Tp, _Alloc>::merge(list& __c, _Comp __comp) { if (this != &__c) { iterator __f1 = begin(); iterator __e1 = end(); iterator __f2 = __c.begin(); iterator __e2 = __c.end(); while (__f1 != __e1 && __f2 != __e2) { if (__comp(*__f2, *__f1)) { size_type __ds = 1; iterator __m2 = _VSTD::next(__f2); for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2, ++__ds) ; base::__sz() += __ds; __c.__sz() -= __ds; - __node_pointer __f = __f2.__ptr_; - __node_pointer __l = __m2.__ptr_->__prev_; + __link_pointer __f = __f2.__ptr_; + __link_pointer __l = __m2.__ptr_->__prev_; __f2 = __m2; base::__unlink_nodes(__f, __l); __m2 = _VSTD::next(__f1); __link_nodes(__f1.__ptr_, __f, __l); __f1 = __m2; } else ++__f1; } splice(__e1, __c); #if _LIBCPP_DEBUG_LEVEL >= 2 __libcpp_db* __db = __get_db(); __c_node* __cn1 = __db->__find_c_and_lock(this); __c_node* __cn2 = __db->__find_c(&__c); for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) { --__p; iterator* __i = static_cast((*__p)->__i_); - if (__i->__ptr_ != static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(__c.__end_))) + if (__i->__ptr_ != __c.__end_as_link()) { __cn1->__add(*__p); (*__p)->__c_ = __cn1; if (--__cn2->end_ != __p) memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); } } __db->unlock(); #endif } } template inline _LIBCPP_INLINE_VISIBILITY void list<_Tp, _Alloc>::sort() { sort(__less()); } template template inline _LIBCPP_INLINE_VISIBILITY void list<_Tp, _Alloc>::sort(_Comp __comp) { __sort(begin(), end(), base::__sz(), __comp); } template template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::__sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp) { switch (__n) { case 0: case 1: return __f1; case 2: if (__comp(*--__e2, *__f1)) { - __node_pointer __f = __e2.__ptr_; + __link_pointer __f = __e2.__ptr_; base::__unlink_nodes(__f, __f); __link_nodes(__f1.__ptr_, __f, __f); return __e2; } return __f1; } size_type __n2 = __n / 2; iterator __e1 = _VSTD::next(__f1, __n2); iterator __r = __f1 = __sort(__f1, __e1, __n2, __comp); iterator __f2 = __e1 = __sort(__e1, __e2, __n - __n2, __comp); if (__comp(*__f2, *__f1)) { iterator __m2 = _VSTD::next(__f2); for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2) ; - __node_pointer __f = __f2.__ptr_; - __node_pointer __l = __m2.__ptr_->__prev_; + __link_pointer __f = __f2.__ptr_; + __link_pointer __l = __m2.__ptr_->__prev_; __r = __f2; __e1 = __f2 = __m2; base::__unlink_nodes(__f, __l); __m2 = _VSTD::next(__f1); __link_nodes(__f1.__ptr_, __f, __l); __f1 = __m2; } else ++__f1; while (__f1 != __e1 && __f2 != __e2) { if (__comp(*__f2, *__f1)) { iterator __m2 = _VSTD::next(__f2); for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2) ; - __node_pointer __f = __f2.__ptr_; - __node_pointer __l = __m2.__ptr_->__prev_; + __link_pointer __f = __f2.__ptr_; + __link_pointer __l = __m2.__ptr_->__prev_; if (__e1 == __f2) __e1 = __m2; __f2 = __m2; base::__unlink_nodes(__f, __l); __m2 = _VSTD::next(__f1); __link_nodes(__f1.__ptr_, __f, __l); __f1 = __m2; } else ++__f1; } return __r; } template void list<_Tp, _Alloc>::reverse() _NOEXCEPT { if (base::__sz() > 1) { iterator __e = end(); for (iterator __i = begin(); __i.__ptr_ != __e.__ptr_;) { _VSTD::swap(__i.__ptr_->__prev_, __i.__ptr_->__next_); __i.__ptr_ = __i.__ptr_->__prev_; } _VSTD::swap(__e.__ptr_->__prev_, __e.__ptr_->__next_); } } template bool list<_Tp, _Alloc>::__invariants() const { return size() == _VSTD::distance(begin(), end()); } #if _LIBCPP_DEBUG_LEVEL >= 2 template bool list<_Tp, _Alloc>::__dereferenceable(const const_iterator* __i) const { - return __i->__ptr_ != static_cast<__node_pointer>( - pointer_traits<__node_base_pointer>::pointer_to(const_cast<__node_base&>(this->__end_))); + return __i->__ptr_ != this->__end_as_link(); } template bool list<_Tp, _Alloc>::__decrementable(const const_iterator* __i) const { return !empty() && __i->__ptr_ != base::__end_.__next_; } template bool list<_Tp, _Alloc>::__addable(const const_iterator* __i, ptrdiff_t __n) const { return false; } template bool list<_Tp, _Alloc>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const { return false; } #endif // _LIBCPP_DEBUG_LEVEL >= 2 template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY void swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_LIST diff --git a/include/map b/include/map index adfb4cdb5e9e..87add437a545 100644 --- a/include/map +++ b/include/map @@ -1,2236 +1,2250 @@ // -*- C++ -*- //===----------------------------- map ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_MAP #define _LIBCPP_MAP /* map synopsis namespace std { template , class Allocator = allocator>> class map { public: // types: typedef Key key_type; typedef T mapped_type; typedef pair value_type; typedef Compare key_compare; typedef Allocator allocator_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; class value_compare : public binary_function { friend class map; protected: key_compare comp; value_compare(key_compare c); public: bool operator()(const value_type& x, const value_type& y) const; }; // construct/copy/destroy: map() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value); explicit map(const key_compare& comp); map(const key_compare& comp, const allocator_type& a); template map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()); template map(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a); map(const map& m); map(map&& m) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); explicit map(const allocator_type& a); map(const map& m, const allocator_type& a); map(map&& m, const allocator_type& a); map(initializer_list il, const key_compare& comp = key_compare()); map(initializer_list il, const key_compare& comp, const allocator_type& a); template map(InputIterator first, InputIterator last, const allocator_type& a) : map(first, last, Compare(), a) {} // C++14 map(initializer_list il, const allocator_type& a) : map(il, Compare(), a) {} // C++14 ~map(); map& operator=(const map& m); map& operator=(map&& m) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); map& operator=(initializer_list il); // iterators: 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; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // element access: 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; // modifiers: template pair emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); pair insert(const value_type& v); + pair insert( value_type&& v); // C++17 template pair insert(P&& p); iterator insert(const_iterator position, const value_type& v); + iterator insert(const_iterator position, value_type&& v); // C++17 template iterator insert(const_iterator position, P&& p); template void insert(InputIterator first, InputIterator last); void insert(initializer_list il); template pair try_emplace(const key_type& k, Args&&... args); // C++17 template pair try_emplace(key_type&& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 template pair insert_or_assign(const key_type& k, M&& obj); // C++17 template pair insert_or_assign(key_type&& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; void swap(map& m) noexcept(allocator_traits::is_always_equal::value && __is_nothrow_swappable::value); // C++17 // observers: allocator_type get_allocator() const noexcept; key_compare key_comp() const; value_compare value_comp() const; // map operations: iterator find(const key_type& k); const_iterator find(const key_type& k) const; template iterator find(const K& x); // C++14 template const_iterator find(const K& x) const; // C++14 template size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template iterator lower_bound(const K& x); // C++14 template const_iterator lower_bound(const K& x) const; // C++14 iterator upper_bound(const key_type& k); const_iterator upper_bound(const key_type& k) const; template iterator upper_bound(const K& x); // C++14 template const_iterator upper_bound(const K& x) const; // C++14 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; template pair equal_range(const K& x); // C++14 template pair equal_range(const K& x) const; // C++14 }; template bool operator==(const map& x, const map& y); template bool operator< (const map& x, const map& y); template bool operator!=(const map& x, const map& y); template bool operator> (const map& x, const map& y); template bool operator>=(const map& x, const map& y); template bool operator<=(const map& x, const map& y); // specialized algorithms: template void swap(map& x, map& y) noexcept(noexcept(x.swap(y))); template , class Allocator = allocator>> class multimap { public: // types: typedef Key key_type; typedef T mapped_type; typedef pair value_type; typedef Compare key_compare; typedef Allocator allocator_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; 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 implementation-defined iterator; typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; class value_compare : public binary_function { friend class multimap; protected: key_compare comp; value_compare(key_compare c); public: bool operator()(const value_type& x, const value_type& y) const; }; // construct/copy/destroy: multimap() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value); explicit multimap(const key_compare& comp); multimap(const key_compare& comp, const allocator_type& a); template multimap(InputIterator first, InputIterator last, const key_compare& comp); template multimap(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a); multimap(const multimap& m); multimap(multimap&& m) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); explicit multimap(const allocator_type& a); multimap(const multimap& m, const allocator_type& a); multimap(multimap&& m, const allocator_type& a); multimap(initializer_list il, const key_compare& comp = key_compare()); multimap(initializer_list il, const key_compare& comp, const allocator_type& a); template multimap(InputIterator first, InputIterator last, const allocator_type& a) : multimap(first, last, Compare(), a) {} // C++14 multimap(initializer_list il, const allocator_type& a) : multimap(il, Compare(), a) {} // C++14 ~multimap(); multimap& operator=(const multimap& m); multimap& operator=(multimap&& m) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); multimap& operator=(initializer_list il); // iterators: 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; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers: template iterator emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& v); + iterator insert( value_type&& v); // C++17 template iterator insert(P&& p); iterator insert(const_iterator position, const value_type& v); + iterator insert(const_iterator position, value_type&& v); // C++17 template iterator insert(const_iterator position, P&& p); template void insert(InputIterator first, InputIterator last); void insert(initializer_list il); 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; void swap(multimap& m) noexcept(allocator_traits::is_always_equal::value && __is_nothrow_swappable::value); // C++17 // observers: allocator_type get_allocator() const noexcept; key_compare key_comp() const; value_compare value_comp() const; // map operations: iterator find(const key_type& k); const_iterator find(const key_type& k) const; template iterator find(const K& x); // C++14 template const_iterator find(const K& x) const; // C++14 template size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template iterator lower_bound(const K& x); // C++14 template const_iterator lower_bound(const K& x) const; // C++14 iterator upper_bound(const key_type& k); const_iterator upper_bound(const key_type& k) const; template iterator upper_bound(const K& x); // C++14 template const_iterator upper_bound(const K& x) const; // C++14 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; template pair equal_range(const K& x); // C++14 template pair equal_range(const K& x) const; // C++14 }; template bool operator==(const multimap& x, const multimap& y); template bool operator< (const multimap& x, const multimap& y); template bool operator!=(const multimap& x, const multimap& y); template bool operator> (const multimap& x, const multimap& y); template bool operator>=(const multimap& x, const multimap& y); template bool operator<=(const multimap& x, const multimap& y); // specialized algorithms: template void swap(multimap& x, multimap& y) noexcept(noexcept(x.swap(y))); } // std */ #include <__config> #include <__tree> #include #include #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template ::value && !__libcpp_is_final<_Compare>::value > class __map_value_compare : private _Compare { public: _LIBCPP_INLINE_VISIBILITY __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) : _Compare() {} _LIBCPP_INLINE_VISIBILITY __map_value_compare(_Compare c) _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) : _Compare(c) {} _LIBCPP_INLINE_VISIBILITY const _Compare& key_comp() const _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _CP& __x, const _CP& __y) const {return static_cast(*this)(__x.__cc.first, __y.__cc.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _CP& __x, const _Key& __y) const {return static_cast(*this)(__x.__cc.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _CP& __y) const {return static_cast(*this)(__x, __y.__cc.first);} void swap(__map_value_compare&__y) _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value) { using _VSTD::swap; swap(static_cast(*this), static_cast(__y)); } #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type operator () ( const _K2& __x, const _CP& __y ) const {return static_cast(*this) (__x, __y.__cc.first);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type operator () (const _CP& __x, const _K2& __y) const {return static_cast(*this) (__x.__cc.first, __y);} #endif }; template class __map_value_compare<_Key, _CP, _Compare, false> { _Compare comp; public: _LIBCPP_INLINE_VISIBILITY __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) : comp() {} _LIBCPP_INLINE_VISIBILITY __map_value_compare(_Compare c) _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) : comp(c) {} _LIBCPP_INLINE_VISIBILITY const _Compare& key_comp() const _NOEXCEPT {return comp;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _CP& __x, const _CP& __y) const {return comp(__x.__cc.first, __y.__cc.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _CP& __x, const _Key& __y) const {return comp(__x.__cc.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _CP& __y) const {return comp(__x, __y.__cc.first);} void swap(__map_value_compare&__y) _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value) { using _VSTD::swap; swap(comp, __y.comp); } #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type operator () ( const _K2& __x, const _CP& __y ) const {return comp (__x, __y.__cc.first);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type operator () (const _CP& __x, const _K2& __y) const {return comp (__x.__cc.first, __y);} #endif }; template inline _LIBCPP_INLINE_VISIBILITY void swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x, __map_value_compare<_Key, _CP, _Compare, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template class __map_node_destructor { typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: typedef typename value_type::value_type::first_type first_type; typedef typename value_type::value_type::second_type second_type; allocator_type& __na_; __map_node_destructor& operator=(const __map_node_destructor&); public: bool __first_constructed; bool __second_constructed; _LIBCPP_INLINE_VISIBILITY explicit __map_node_destructor(allocator_type& __na) _NOEXCEPT : __na_(__na), __first_constructed(false), __second_constructed(false) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __map_node_destructor(__tree_node_destructor&& __x) _NOEXCEPT : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { __x.__value_constructed = false; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.second)); if (__first_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; template class map; template class multimap; template class __map_const_iterator; #if __cplusplus >= 201103L template union __value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; typedef pair __nc_value_type; value_type __cc; __nc_value_type __nc; template _LIBCPP_INLINE_VISIBILITY __value_type(_Args&& ...__args) : __cc(std::forward<_Args>(__args)...) {} _LIBCPP_INLINE_VISIBILITY __value_type(const __value_type& __v) : __cc(__v.__cc) {} _LIBCPP_INLINE_VISIBILITY __value_type(__value_type& __v) : __cc(__v.__cc) {} _LIBCPP_INLINE_VISIBILITY __value_type(__value_type&& __v) : __nc(std::move(__v.__nc)) {} _LIBCPP_INLINE_VISIBILITY __value_type& operator=(const __value_type& __v) {__nc = __v.__cc; return *this;} _LIBCPP_INLINE_VISIBILITY __value_type& operator=(__value_type&& __v) {__nc = std::move(__v.__nc); return *this;} _LIBCPP_INLINE_VISIBILITY ~__value_type() {__cc.~value_type();} }; #else template struct __value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; value_type __cc; _LIBCPP_INLINE_VISIBILITY __value_type() {} template _LIBCPP_INLINE_VISIBILITY __value_type(const _A0& __a0) : __cc(__a0) {} template _LIBCPP_INLINE_VISIBILITY __value_type(const _A0& __a0, const _A1& __a1) : __cc(__a0, __a1) {} }; #endif template struct __extract_key_value_types; template struct __extract_key_value_types<__value_type<_Key, _Tp> > { typedef _Key const __key_type; typedef _Tp __mapped_type; }; template class _LIBCPP_TYPE_VIS_ONLY __map_iterator { _TreeIterator __i_; typedef typename _TreeIterator::__pointer_traits __pointer_traits; typedef typename _TreeIterator::value_type __value_type; typedef typename __extract_key_value_types<__value_type>::__key_type __key_type; typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type; public: typedef bidirectional_iterator_tag iterator_category; typedef pair<__key_type, __mapped_type> value_type; typedef typename _TreeIterator::difference_type difference_type; typedef value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + pointer; _LIBCPP_INLINE_VISIBILITY __map_iterator() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __i_->__cc;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__cc);} _LIBCPP_INLINE_VISIBILITY __map_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __map_iterator operator++(int) { __map_iterator __t(*this); ++(*this); return __t; } _LIBCPP_INLINE_VISIBILITY __map_iterator& operator--() {--__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __map_iterator operator--(int) { __map_iterator __t(*this); --(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __map_iterator& __x, const __map_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __map_iterator& __x, const __map_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY map; template friend class _LIBCPP_TYPE_VIS_ONLY multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; }; template class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator { _TreeIterator __i_; typedef typename _TreeIterator::__pointer_traits __pointer_traits; typedef typename _TreeIterator::value_type __value_type; typedef typename __extract_key_value_types<__value_type>::__key_type __key_type; typedef typename __extract_key_value_types<__value_type>::__mapped_type __mapped_type; public: typedef bidirectional_iterator_tag iterator_category; typedef pair<__key_type, __mapped_type> value_type; typedef typename _TreeIterator::difference_type difference_type; typedef const value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + pointer; _LIBCPP_INLINE_VISIBILITY __map_const_iterator() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY __map_const_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY __map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __i_->__cc;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__cc);} _LIBCPP_INLINE_VISIBILITY __map_const_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __map_const_iterator operator++(int) { __map_const_iterator __t(*this); ++(*this); return __t; } _LIBCPP_INLINE_VISIBILITY __map_const_iterator& operator--() {--__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __map_const_iterator operator--(int) { __map_const_iterator __t(*this); --(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __map_const_iterator& __x, const __map_const_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __map_const_iterator& __x, const __map_const_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY map; template friend class _LIBCPP_TYPE_VIS_ONLY multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; }; template , class _Allocator = allocator > > class _LIBCPP_TYPE_VIS_ONLY map { public: // types: typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; typedef pair __nc_value_type; typedef _Compare key_compare; typedef _Allocator allocator_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); class _LIBCPP_TYPE_VIS_ONLY value_compare : public binary_function { friend class map; protected: key_compare comp; _LIBCPP_INLINE_VISIBILITY value_compare(key_compare c) : comp(c) {} public: _LIBCPP_INLINE_VISIBILITY bool operator()(const value_type& __x, const value_type& __y) const {return comp(__x.first, __y.first);} }; private: typedef _VSTD::__value_type __value_type; typedef __map_value_compare __vc; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __tree<__value_type, __vc, __allocator_type> __base; typedef typename __base::__node_traits __node_traits; typedef allocator_traits __alloc_traits; __base __tree_; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __map_iterator iterator; typedef __map_const_iterator const_iterator; typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; _LIBCPP_INLINE_VISIBILITY map() _NOEXCEPT_( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value) : __tree_(__vc(key_compare())) {} _LIBCPP_INLINE_VISIBILITY explicit map(const key_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value) : __tree_(__vc(__comp)) {} _LIBCPP_INLINE_VISIBILITY explicit map(const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) {} template _LIBCPP_INLINE_VISIBILITY map(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__f, __l); } template _LIBCPP_INLINE_VISIBILITY map(_InputIterator __f, _InputIterator __l, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) { insert(__f, __l); } #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : map(__f, __l, key_compare(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY map(const map& __m) : __tree_(__m.__tree_) { insert(__m.begin(), __m.end()); } _LIBCPP_INLINE_VISIBILITY map& operator=(const map& __m) { #if __cplusplus >= 201103L __tree_ = __m.__tree_; #else if (this != &__m) { __tree_.clear(); __tree_.value_comp() = __m.__tree_.value_comp(); __tree_.__copy_assign_alloc(__m.__tree_); insert(__m.begin(), __m.end()); } #endif return *this; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY map(map&& __m) _NOEXCEPT_(is_nothrow_move_constructible<__base>::value) : __tree_(_VSTD::move(__m.__tree_)) { } map(map&& __m, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY map& operator=(map&& __m) _NOEXCEPT_(is_nothrow_move_assignable<__base>::value) { __tree_ = _VSTD::move(__m.__tree_); return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY map(initializer_list __il, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__il.begin(), __il.end()); } _LIBCPP_INLINE_VISIBILITY map(initializer_list __il, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) { insert(__il.begin(), __il.end()); } #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY map(initializer_list __il, const allocator_type& __a) : map(__il, key_compare(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY map& operator=(initializer_list __il) { __tree_.__assign_unique(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY explicit map(const allocator_type& __a) : __tree_(__a) { } _LIBCPP_INLINE_VISIBILITY map(const map& __m, const allocator_type& __a) : __tree_(__m.__tree_.value_comp(), __a) { insert(__m.begin(), __m.end()); } _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __tree_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __tree_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __tree_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __tree_.end();} _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return end();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __tree_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __tree_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __tree_.max_size();} mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 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 allocator_type get_allocator() const _NOEXCEPT {return __tree_.__alloc();} _LIBCPP_INLINE_VISIBILITY key_compare key_comp() const {return __tree_.value_comp().key_comp();} _LIBCPP_INLINE_VISIBILITY value_compare value_comp() const {return value_compare(__tree_.value_comp().key_comp());} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template pair emplace(_Args&& ...__args); template iterator emplace_hint(const_iterator __p, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS template ::value>::type> _LIBCPP_INLINE_VISIBILITY pair insert(_Pp&& __p) {return __tree_.__insert_unique(_VSTD::forward<_Pp>(__p));} template ::value>::type> _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __pos, _Pp&& __p) {return __tree_.__insert_unique(__pos.__i_, _VSTD::forward<_Pp>(__p));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY pair insert(const value_type& __v) {return __tree_.__insert_unique(__v);} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, const value_type& __v) {return __tree_.__insert_unique(__p.__i_, __v);} +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) + _LIBCPP_INLINE_VISIBILITY + pair + insert( value_type&& __v) {return __tree_.__insert_unique(_VSTD::forward(__v));} + + _LIBCPP_INLINE_VISIBILITY + iterator + insert(const_iterator __p, value_type&& __v) + {return __tree_.__insert_unique(__p.__i_, _VSTD::forward(__v));} +#endif + template _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __f, _InputIterator __l) { for (const_iterator __e = cend(); __f != __l; ++__f) insert(__e.__i_, *__f); } #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #if _LIBCPP_STD_VER > 14 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template _LIBCPP_INLINE_VISIBILITY pair try_emplace(const key_type& __k, _Args&&... __args) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) return _VSTD::make_pair(__p, false); else return _VSTD::make_pair( emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)), true); } template _LIBCPP_INLINE_VISIBILITY pair try_emplace(key_type&& __k, _Args&&... __args) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) return _VSTD::make_pair(__p, false); else return _VSTD::make_pair( emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)), true); } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) return __p; else return emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) return __p; else return emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(const key_type& __k, _Vp&& __v) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) { __p->second = _VSTD::forward<_Vp>(__v); return _VSTD::make_pair(__p, false); } return _VSTD::make_pair(emplace_hint(__p, __k, _VSTD::forward<_Vp>(__v)), true); } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(key_type&& __k, _Vp&& __v) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) { __p->second = _VSTD::forward<_Vp>(__v); return _VSTD::make_pair(__p, false); } return _VSTD::make_pair(emplace_hint(__p, _VSTD::move(__k), _VSTD::forward<_Vp>(__v)), true); } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) { __p->second = _VSTD::forward<_Vp>(__v); return __p; } return emplace_hint(__h, __k, _VSTD::forward<_Vp>(__v)); } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { iterator __p = lower_bound(__k); if ( __p != end() && !key_comp()(__k, __p->first)) { __p->second = _VSTD::forward<_Vp>(__v); return __p; } return emplace_hint(__h, _VSTD::move(__k), _VSTD::forward<_Vp>(__v)); } #endif #endif #endif _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __tree_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY iterator erase(iterator __p) {return __tree_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __tree_.__erase_unique(__k);} _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __f, const_iterator __l) {return __tree_.erase(__f.__i_, __l.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} _LIBCPP_INLINE_VISIBILITY void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable<__base>::value) {__tree_.swap(__m.__tree_);} _LIBCPP_INLINE_VISIBILITY iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type find(const _K2& __k) {return __tree_.find(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type find(const _K2& __k) const {return __tree_.find(__k);} #endif _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_unique(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_unique(__k);} #endif _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type lower_bound(const _K2& __k) {return __tree_.lower_bound(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type lower_bound(const _K2& __k) const {return __tree_.lower_bound(__k);} #endif _LIBCPP_INLINE_VISIBILITY iterator upper_bound(const key_type& __k) {return __tree_.upper_bound(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type upper_bound(const _K2& __k) {return __tree_.upper_bound(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type upper_bound(const _K2& __k) const {return __tree_.upper_bound(__k);} #endif _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __tree_.__equal_range_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __tree_.__equal_range_unique(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair>::type equal_range(const _K2& __k) {return __tree_.__equal_range_unique(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair>::type equal_range(const _K2& __k) const {return __tree_.__equal_range_unique(__k);} #endif private: typedef typename __base::__node __node; typedef typename __base::__node_allocator __node_allocator; typedef typename __base::__node_pointer __node_pointer; typedef typename __base::__node_const_pointer __node_const_pointer; typedef typename __base::__node_base_pointer __node_base_pointer; typedef typename __base::__node_base_const_pointer __node_base_const_pointer; typedef __map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node(); template __node_holder __construct_node(_A0&& __a0); __node_holder __construct_node_with_key(key_type&& __k); #ifndef _LIBCPP_HAS_NO_VARIADICS template __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS #endif __node_holder __construct_node_with_key(const key_type& __k); __node_base_pointer& __find_equal_key(__node_base_pointer& __parent, const key_type& __k); __node_base_const_pointer __find_equal_key(__node_base_const_pointer& __parent, const key_type& __k) const; }; // Find place to insert if __k doesn't exist // Set __parent to parent of null leaf // Return reference to null leaf // If __k exists, set parent to node of __k and return reference to node of __k template typename map<_Key, _Tp, _Compare, _Allocator>::__node_base_pointer& map<_Key, _Tp, _Compare, _Allocator>::__find_equal_key(__node_base_pointer& __parent, const key_type& __k) { __node_pointer __nd = __tree_.__root(); if (__nd != nullptr) { while (true) { if (__tree_.value_comp().key_comp()(__k, __nd->__value_.__cc.first)) { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__left_; } } else if (__tree_.value_comp().key_comp()(__nd->__value_.__cc.first, __k)) { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { __parent = static_cast<__node_base_pointer>(__nd); return __parent->__right_; } } else { __parent = static_cast<__node_base_pointer>(__nd); return __parent; } } } __parent = static_cast<__node_base_pointer>(__tree_.__end_node()); return __parent->__left_; } // Find __k // Set __parent to parent of null leaf and // return reference to null leaf iv __k does not exist. // If __k exists, set parent to node of __k and return reference to node of __k template typename map<_Key, _Tp, _Compare, _Allocator>::__node_base_const_pointer map<_Key, _Tp, _Compare, _Allocator>::__find_equal_key(__node_base_const_pointer& __parent, const key_type& __k) const { __node_const_pointer __nd = __tree_.__root(); if (__nd != nullptr) { while (true) { if (__tree_.value_comp().key_comp()(__k, __nd->__value_.__cc.first)) { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { __parent = static_cast<__node_base_pointer>(__nd); return const_cast(__parent->__left_); } } else if (__tree_.value_comp().key_comp()(__nd->__value_.__cc.first, __k)) { if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { __parent = static_cast<__node_base_pointer>(__nd); return const_cast(__parent->__right_); } } else { __parent = static_cast<__node_base_pointer>(__nd); return __parent; } } } __parent = static_cast<__node_base_pointer>(__tree_.__end_node()); return const_cast(__parent->__left_); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) : __tree_(_VSTD::move(__m.__tree_), __a) { if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) __tree_.__insert_unique(__e.__i_, _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_)); } } template typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node() { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first)); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return __h; } template template typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(key_type&& __k) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first), _VSTD::move(__k)); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return __h; } #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first), __k); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal_key(__parent, __k); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __node_holder __h = __construct_node_with_key(__k); __tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return __r->__value_.__cc.second; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal_key(__parent, __k); __node_pointer __r = static_cast<__node_pointer>(__child); if (__child == nullptr) { __node_holder __h = __construct_node_with_key(_VSTD::move(__k)); __tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return __r->__value_.__cc.second; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { __node_base_pointer __parent; __node_base_pointer& __child = __find_equal_key(__parent, __k); #ifndef _LIBCPP_NO_EXCEPTIONS if (__child == nullptr) throw out_of_range("map::at: key not found"); #endif // _LIBCPP_NO_EXCEPTIONS return static_cast<__node_pointer>(__child)->__value_.__cc.second; } template const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { __node_base_const_pointer __parent; __node_base_const_pointer __child = __find_equal_key(__parent, __k); #ifndef _LIBCPP_NO_EXCEPTIONS if (__child == nullptr) throw out_of_range("map::at: key not found"); #endif // _LIBCPP_NO_EXCEPTIONS return static_cast<__node_const_pointer>(__child)->__value_.__cc.second; } #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template template pair::iterator, bool> map<_Key, _Tp, _Compare, _Allocator>::emplace(_Args&& ...__args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); pair __r = __tree_.__node_insert_unique(__h.get()); if (__r.second) __h.release(); return __r; } template template typename map<_Key, _Tp, _Compare, _Allocator>::iterator map<_Key, _Tp, _Compare, _Allocator>::emplace_hint(const_iterator __p, _Args&& ...__args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __tree_.__node_insert_unique(__p.__i_, __h.get()); if (__r.__i_.__ptr_ == __h.get()) __h.release(); return __r; } #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY void swap(map<_Key, _Tp, _Compare, _Allocator>& __x, map<_Key, _Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template , class _Allocator = allocator > > class _LIBCPP_TYPE_VIS_ONLY multimap { public: // types: typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; typedef pair __nc_value_type; typedef _Compare key_compare; typedef _Allocator allocator_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); class _LIBCPP_TYPE_VIS_ONLY value_compare : public binary_function { friend class multimap; protected: key_compare comp; _LIBCPP_INLINE_VISIBILITY value_compare(key_compare c) : comp(c) {} public: _LIBCPP_INLINE_VISIBILITY bool operator()(const value_type& __x, const value_type& __y) const {return comp(__x.first, __y.first);} }; private: typedef _VSTD::__value_type __value_type; typedef __map_value_compare __vc; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __tree<__value_type, __vc, __allocator_type> __base; typedef typename __base::__node_traits __node_traits; typedef allocator_traits __alloc_traits; __base __tree_; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __map_iterator iterator; typedef __map_const_iterator const_iterator; typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; _LIBCPP_INLINE_VISIBILITY multimap() _NOEXCEPT_( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value) : __tree_(__vc(key_compare())) {} _LIBCPP_INLINE_VISIBILITY explicit multimap(const key_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible::value && is_nothrow_copy_constructible::value) : __tree_(__vc(__comp)) {} _LIBCPP_INLINE_VISIBILITY explicit multimap(const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) {} template _LIBCPP_INLINE_VISIBILITY multimap(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__f, __l); } template _LIBCPP_INLINE_VISIBILITY multimap(_InputIterator __f, _InputIterator __l, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) { insert(__f, __l); } #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY multimap(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : multimap(__f, __l, key_compare(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY multimap(const multimap& __m) : __tree_(__m.__tree_.value_comp(), __alloc_traits::select_on_container_copy_construction(__m.__tree_.__alloc())) { insert(__m.begin(), __m.end()); } _LIBCPP_INLINE_VISIBILITY multimap& operator=(const multimap& __m) { #if __cplusplus >= 201103L __tree_ = __m.__tree_; #else if (this != &__m) { __tree_.clear(); __tree_.value_comp() = __m.__tree_.value_comp(); __tree_.__copy_assign_alloc(__m.__tree_); insert(__m.begin(), __m.end()); } #endif return *this; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY multimap(multimap&& __m) _NOEXCEPT_(is_nothrow_move_constructible<__base>::value) : __tree_(_VSTD::move(__m.__tree_)) { } multimap(multimap&& __m, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY multimap& operator=(multimap&& __m) _NOEXCEPT_(is_nothrow_move_assignable<__base>::value) { __tree_ = _VSTD::move(__m.__tree_); return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY multimap(initializer_list __il, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__il.begin(), __il.end()); } _LIBCPP_INLINE_VISIBILITY multimap(initializer_list __il, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), __a) { insert(__il.begin(), __il.end()); } #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY multimap(initializer_list __il, const allocator_type& __a) : multimap(__il, key_compare(), __a) {} #endif _LIBCPP_INLINE_VISIBILITY multimap& operator=(initializer_list __il) { __tree_.__assign_multi(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY explicit multimap(const allocator_type& __a) : __tree_(__a) { } _LIBCPP_INLINE_VISIBILITY multimap(const multimap& __m, const allocator_type& __a) : __tree_(__m.__tree_.value_comp(), __a) { insert(__m.begin(), __m.end()); } _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __tree_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __tree_.begin();} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __tree_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __tree_.end();} _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return end();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __tree_.size() == 0;} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __tree_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __tree_.max_size();} _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return __tree_.__alloc();} _LIBCPP_INLINE_VISIBILITY key_compare key_comp() const {return __tree_.value_comp().key_comp();} _LIBCPP_INLINE_VISIBILITY value_compare value_comp() const {return value_compare(__tree_.value_comp().key_comp());} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template iterator emplace(_Args&& ...__args); template iterator emplace_hint(const_iterator __p, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS template ::value>::type> _LIBCPP_INLINE_VISIBILITY iterator insert(_Pp&& __p) {return __tree_.__insert_multi(_VSTD::forward<_Pp>(__p));} template ::value>::type> _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __pos, _Pp&& __p) {return __tree_.__insert_multi(__pos.__i_, _VSTD::forward<_Pp>(__p));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY iterator insert(const value_type& __v) {return __tree_.__insert_multi(__v);} _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, const value_type& __v) {return __tree_.__insert_multi(__p.__i_, __v);} +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) + _LIBCPP_INLINE_VISIBILITY + iterator insert( value_type&& __v) {return __tree_.__insert_multi(_VSTD::forward(__v));} + + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __p, value_type&& __v) + {return __tree_.__insert_multi(__p.__i_, _VSTD::forward(__v));} +#endif + template _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __f, _InputIterator __l) { for (const_iterator __e = cend(); __f != __l; ++__f) __tree_.__insert_multi(__e.__i_, *__f); } #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __tree_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY iterator erase(iterator __p) {return __tree_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY size_type erase(const key_type& __k) {return __tree_.__erase_multi(__k);} _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __f, const_iterator __l) {return __tree_.erase(__f.__i_, __l.__i_);} _LIBCPP_INLINE_VISIBILITY void clear() {__tree_.clear();} _LIBCPP_INLINE_VISIBILITY void swap(multimap& __m) _NOEXCEPT_(__is_nothrow_swappable<__base>::value) {__tree_.swap(__m.__tree_);} _LIBCPP_INLINE_VISIBILITY iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type find(const _K2& __k) {return __tree_.find(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type find(const _K2& __k) const {return __tree_.find(__k);} #endif _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_multi(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type lower_bound(const _K2& __k) {return __tree_.lower_bound(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type lower_bound(const _K2& __k) const {return __tree_.lower_bound(__k);} #endif _LIBCPP_INLINE_VISIBILITY iterator upper_bound(const key_type& __k) {return __tree_.upper_bound(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type upper_bound(const _K2& __k) {return __tree_.upper_bound(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,const_iterator>::type upper_bound(const _K2& __k) const {return __tree_.upper_bound(__k);} #endif _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __tree_.__equal_range_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __tree_.__equal_range_multi(__k);} #if _LIBCPP_STD_VER > 11 template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair>::type equal_range(const _K2& __k) {return __tree_.__equal_range_multi(__k);} template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair>::type equal_range(const _K2& __k) const {return __tree_.__equal_range_multi(__k);} #endif private: typedef typename __base::__node __node; typedef typename __base::__node_allocator __node_allocator; typedef typename __base::__node_pointer __node_pointer; typedef typename __base::__node_const_pointer __node_const_pointer; typedef __map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node(); template __node_holder __construct_node(_A0&& __a0); #ifndef _LIBCPP_HAS_NO_VARIADICS template __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const allocator_type& __a) : __tree_(_VSTD::move(__m.__tree_), __a) { if (__a != __m.get_allocator()) { const_iterator __e = cend(); while (!__m.empty()) __tree_.__insert_multi(__e.__i_, _VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_)); } } template typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node() { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first)); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return __h; } template template typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename multimap<_Key, _Tp, _Compare, _Allocator>::__node_holder multimap<_Key, _Tp, _Compare, _Allocator>::__construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template template typename multimap<_Key, _Tp, _Compare, _Allocator>::iterator multimap<_Key, _Tp, _Compare, _Allocator>::emplace(_Args&& ...__args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __tree_.__node_insert_multi(__h.get()); __h.release(); return __r; } template template typename multimap<_Key, _Tp, _Compare, _Allocator>::iterator multimap<_Key, _Tp, _Compare, _Allocator>::emplace_hint(const_iterator __p, _Args&& ...__args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __tree_.__node_insert_multi(__p.__i_, __h.get()); __h.release(); return __r; } #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY void swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x, multimap<_Key, _Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_MAP diff --git a/include/unordered_map b/include/unordered_map index 3c774d4094e0..85a54a7b6ddb 100644 --- a/include/unordered_map +++ b/include/unordered_map @@ -1,2251 +1,2239 @@ // -*- C++ -*- //===-------------------------- unordered_map -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_UNORDERED_MAP #define _LIBCPP_UNORDERED_MAP /* unordered_map synopsis #include namespace std { template , class Pred = equal_to, class Alloc = allocator>> class unordered_map { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; unordered_map() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value); explicit unordered_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template unordered_map(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit unordered_map(const allocator_type&); unordered_map(const unordered_map&); unordered_map(const unordered_map&, const Allocator&); unordered_map(unordered_map&&) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); unordered_map(unordered_map&&, const Allocator&); unordered_map(initializer_list, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(size_type n, const allocator_type& a) : unordered_map(n, hasher(), key_equal(), a) {} // C++14 unordered_map(size_type n, const hasher& hf, const allocator_type& a) : unordered_map(n, hf, key_equal(), a) {} // C++14 template unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_map(f, l, n, hasher(), key_equal(), a) {} // C++14 template unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) {} // C++14 unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) {} // C++14 unordered_map(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(il, n, hf, key_equal(), a) {} // C++14 ~unordered_map(); unordered_map& operator=(const unordered_map&); unordered_map& operator=(unordered_map&&) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); unordered_map& operator=(initializer_list); allocator_type get_allocator() const noexcept; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; template pair emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); pair insert(const value_type& obj); template pair insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); void insert(initializer_list); template pair try_emplace(const key_type& k, Args&&... args); // C++17 template pair try_emplace(key_type&& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 template iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 template pair insert_or_assign(const key_type& k, M&& obj); // C++17 template pair insert_or_assign(key_type&& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 template iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); iterator erase(const_iterator first, const_iterator last); void clear() noexcept; void swap(unordered_map&) noexcept( (!allocator_type::propagate_on_container_swap::value || __is_nothrow_swappable::value) && __is_nothrow_swappable::value && __is_nothrow_swappable::value); hasher hash_function() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; 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 void swap(unordered_map& x, unordered_map& y) noexcept(noexcept(x.swap(y))); template bool operator==(const unordered_map& x, const unordered_map& y); template bool operator!=(const unordered_map& x, const unordered_map& y); template , class Pred = equal_to, class Alloc = allocator>> class unordered_multimap { public: // types typedef Key key_type; typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; typedef Alloc allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits::pointer pointer; typedef typename allocator_traits::const_pointer const_pointer; typedef typename allocator_traits::size_type size_type; typedef typename allocator_traits::difference_type difference_type; typedef /unspecified/ iterator; typedef /unspecified/ const_iterator; typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; unordered_multimap() noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && is_nothrow_default_constructible::value); explicit unordered_multimap(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template unordered_multimap(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); explicit unordered_multimap(const allocator_type&); unordered_multimap(const unordered_multimap&); unordered_multimap(const unordered_multimap&, const Allocator&); unordered_multimap(unordered_multimap&&) noexcept( is_nothrow_move_constructible::value && is_nothrow_move_constructible::value && is_nothrow_move_constructible::value); unordered_multimap(unordered_multimap&&, const Allocator&); unordered_multimap(initializer_list, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(size_type n, const allocator_type& a) : unordered_multimap(n, hasher(), key_equal(), a) {} // C++14 unordered_multimap(size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(n, hf, key_equal(), a) {} // C++14 template unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_multimap(f, l, n, hasher(), key_equal(), a) {} // C++14 template unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) {} // C++14 unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) {} // C++14 unordered_multimap(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(il, n, hf, key_equal(), a) {} // C++14 ~unordered_multimap(); unordered_multimap& operator=(const unordered_multimap&); unordered_multimap& operator=(unordered_multimap&&) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value && is_nothrow_move_assignable::value); unordered_multimap& operator=(initializer_list); allocator_type get_allocator() const noexcept; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; template iterator emplace(Args&&... args); template iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& obj); template iterator insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); void insert(initializer_list); 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; void swap(unordered_multimap&) noexcept( (!allocator_type::propagate_on_container_swap::value || __is_nothrow_swappable::value) && __is_nothrow_swappable::value && __is_nothrow_swappable::value); hasher hash_function() const; key_equal key_eq() const; iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; pair equal_range(const key_type& k); pair equal_range(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 void swap(unordered_multimap& x, unordered_multimap& y) noexcept(noexcept(x.swap(y))); template bool operator==(const unordered_multimap& x, const unordered_multimap& y); template bool operator!=(const unordered_multimap& x, const unordered_multimap& y); } // std */ #include <__config> #include <__hash_table> #include #include #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template ::value && !__libcpp_is_final<_Hash>::value > class __unordered_map_hasher : private _Hash { public: _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher() _NOEXCEPT_(is_nothrow_default_constructible<_Hash>::value) : _Hash() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : _Hash(__h) {} _LIBCPP_INLINE_VISIBILITY const _Hash& hash_function() const _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Cp& __x) const {return static_cast(*this)(__x.__cc.first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return static_cast(*this)(__x);} void swap(__unordered_map_hasher&__y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { using _VSTD::swap; swap(static_cast(*this), static_cast(__y)); } }; template class __unordered_map_hasher<_Key, _Cp, _Hash, 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.__cc.first);} _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return __hash_(__x);} void swap(__unordered_map_hasher&__y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { using _VSTD::swap; swap(__hash_, __y.__hash_); } }; template inline _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x, __unordered_map_hasher<_Key, _Cp, _Hash, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template ::value && !__libcpp_is_final<_Pred>::value > class __unordered_map_equal : private _Pred { public: _LIBCPP_INLINE_VISIBILITY __unordered_map_equal() _NOEXCEPT_(is_nothrow_default_constructible<_Pred>::value) : _Pred() {} _LIBCPP_INLINE_VISIBILITY __unordered_map_equal(const _Pred& __p) _NOEXCEPT_(is_nothrow_copy_constructible<_Pred>::value) : _Pred(__p) {} _LIBCPP_INLINE_VISIBILITY const _Pred& key_eq() const _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Cp& __y) const {return static_cast(*this)(__x.__cc.first, __y.__cc.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Key& __y) const {return static_cast(*this)(__x.__cc.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return static_cast(*this)(__x, __y.__cc.first);} void swap(__unordered_map_equal&__y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { using _VSTD::swap; swap(static_cast(*this), static_cast(__y)); } }; template class __unordered_map_equal<_Key, _Cp, _Pred, 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.__cc.first, __y.__cc.first);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _Key& __y) const {return __pred_(__x.__cc.first, __y);} _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return __pred_(__x, __y.__cc.first);} void swap(__unordered_map_equal&__y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { using _VSTD::swap; swap(__pred_, __y.__pred_); } }; template inline _LIBCPP_INLINE_VISIBILITY void swap(__unordered_map_equal<_Key, _Cp, _Pred, __b>& __x, __unordered_map_equal<_Key, _Cp, _Pred, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template class __hash_map_node_destructor { typedef _Alloc allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::value_type::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; private: typedef typename value_type::value_type::first_type first_type; typedef typename value_type::value_type::second_type second_type; 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_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(__hash_node_destructor&& __x) _NOEXCEPT : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { __x.__value_constructed = false; } #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY __hash_map_node_destructor(const __hash_node_destructor& __x) : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) { const_cast(__x.__value_constructed) = false; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.second)); if (__first_constructed) __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } }; #if __cplusplus >= 201103L template union __hash_value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; typedef pair __nc_value_type; value_type __cc; __nc_value_type __nc; template _LIBCPP_INLINE_VISIBILITY __hash_value_type(_Args&& ...__args) : __cc(std::forward<_Args>(__args)...) {} _LIBCPP_INLINE_VISIBILITY __hash_value_type(const __hash_value_type& __v) : __cc(__v.__cc) {} _LIBCPP_INLINE_VISIBILITY __hash_value_type(__hash_value_type&& __v) : __nc(_VSTD::move(__v.__nc)) {} _LIBCPP_INLINE_VISIBILITY __hash_value_type& operator=(const __hash_value_type& __v) {__nc = __v.__cc; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_value_type& operator=(__hash_value_type&& __v) {__nc = _VSTD::move(__v.__nc); return *this;} _LIBCPP_INLINE_VISIBILITY ~__hash_value_type() {__cc.~value_type();} }; #else template struct __hash_value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair value_type; value_type __cc; _LIBCPP_INLINE_VISIBILITY __hash_value_type() {} template _LIBCPP_INLINE_VISIBILITY __hash_value_type(const _A0& __a0) : __cc(__a0) {} template _LIBCPP_INLINE_VISIBILITY __hash_value_type(const _A0& __a0, const _A1& __a1) : __cc(__a0, __a1) {} }; #endif template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator { _HashIterator __i_; - typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::value_type::first_type key_type; typedef typename _HashIterator::value_type::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + 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_->__cc;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__cc);} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_iterator operator++(int) { __hash_map_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; }; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator { _HashIterator __i_; - typedef pointer_traits __pointer_traits; typedef const typename _HashIterator::value_type::value_type::first_type key_type; typedef typename _HashIterator::value_type::value_type::second_type mapped_type; public: typedef forward_iterator_tag iterator_category; typedef pair value_type; typedef typename _HashIterator::difference_type difference_type; typedef const value_type& reference; - typedef typename __pointer_traits::template -#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES - rebind -#else - rebind::other -#endif - pointer; + typedef typename __rebind_pointer::type + pointer; _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator( __hash_map_iterator __i) _NOEXCEPT : __i_(__i.__i_) {} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __i_->__cc;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return pointer_traits::pointer_to(__i_->__cc);} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator& operator++() {++__i_; return *this;} _LIBCPP_INLINE_VISIBILITY __hash_map_const_iterator operator++(int) { __hash_map_const_iterator __t(*this); ++(*this); return __t; } friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ == __y.__i_;} friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ != __y.__i_;} template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; }; template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TYPE_VIS_ONLY unordered_map { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef pair __nc_value_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); private: typedef __hash_value_type __value_type; typedef __unordered_map_hasher __hasher; typedef __unordered_map_equal __key_equal; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_pointer __node_pointer; typedef typename __table::__node_const_pointer __node_const_pointer; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; _LIBCPP_INLINE_VISIBILITY unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } explicit unordered_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template unordered_map(_InputIterator __first, _InputIterator __last); template unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); 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_HAS_NO_RVALUE_REFERENCES unordered_map(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); unordered_map(unordered_map&& __u, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS unordered_map(initializer_list __il); unordered_map(initializer_list __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_map(initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY unordered_map(size_type __n, const allocator_type& __a) : unordered_map(__n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__n, __hf, key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a) : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_map(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__il, __n, __hf, key_equal(), __a) {} #endif // ~unordered_map() = default; _LIBCPP_INLINE_VISIBILITY unordered_map& operator=(const unordered_map& __u) { #if __cplusplus >= 201103L __table_ = __u.__table_; #else if (this != &__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_HAS_NO_RVALUE_REFERENCES unordered_map& operator=(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); #endif #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS unordered_map& operator=(initializer_list __il); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(__table_.__node_alloc());} _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();} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template pair emplace(_Args&&... __args); template _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_DEBUG_LEVEL >= 2 iterator emplace_hint(const_iterator __p, _Args&&... __args) { _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered_map::emplace_hint(const_iterator, args...) called with an iterator not" " referring to this unordered_map"); return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; } #else iterator emplace_hint(const_iterator, _Args&&... __args) {return emplace(_VSTD::forward<_Args>(__args)...).first;} #endif #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY pair insert(const value_type& __x) {return __table_.__insert_unique(__x);} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template ::value>::type> _LIBCPP_INLINE_VISIBILITY pair insert(_Pp&& __x) {return __table_.__insert_unique(_VSTD::forward<_Pp>(__x));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_DEBUG_LEVEL >= 2 iterator insert(const_iterator __p, const value_type& __x) { _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered_map::insert(const_iterator, const value_type&) called with an iterator not" " referring to this unordered_map"); return insert(__x).first; } #else iterator insert(const_iterator, const value_type& __x) {return insert(__x).first;} #endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template ::value>::type> _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_DEBUG_LEVEL >= 2 iterator insert(const_iterator __p, _Pp&& __x) { _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, "unordered_map::insert(const_iterator, value_type&&) called with an iterator not" " referring to this unordered_map"); return insert(_VSTD::forward<_Pp>(__x)).first; } #else iterator insert(const_iterator, _Pp&& __x) {return insert(_VSTD::forward<_Pp>(__x)).first;} #endif #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void insert(_InputIterator __first, _InputIterator __last); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #if _LIBCPP_STD_VER > 14 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template _LIBCPP_INLINE_VISIBILITY pair try_emplace(const key_type& __k, _Args&&... __args) { iterator __p = __table_.find(__k); if ( __p != end()) return _VSTD::make_pair(__p, false); else return _VSTD::make_pair( emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)), true); } template _LIBCPP_INLINE_VISIBILITY pair try_emplace(key_type&& __k, _Args&&... __args) { iterator __p = __table_.find(__k); if ( __p != end()) return _VSTD::make_pair(__p, false); else return _VSTD::make_pair( emplace_hint(__p, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)), true); } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { iterator __p = __table_.find(__k); if ( __p != end()) return __p; else return emplace_hint(__h, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(__k), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { iterator __p = __table_.find(__k); if ( __p != end()) return __p; else return emplace_hint(__h, _VSTD::piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__k)), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(const key_type& __k, _Vp&& __v) { iterator __p = __table_.find(__k); if ( __p != end()) { __p->second = _VSTD::move(__v); return _VSTD::make_pair(__p, false); } return _VSTD::make_pair(emplace_hint(__p, __k, _VSTD::forward<_Vp>(__v)), true); } template _LIBCPP_INLINE_VISIBILITY pair insert_or_assign(key_type&& __k, _Vp&& __v) { iterator __p = __table_.find(__k); if ( __p != end()) { __p->second = _VSTD::move(__v); return _VSTD::make_pair(__p, false); } return _VSTD::make_pair(emplace_hint(__p, _VSTD::forward(__k), _VSTD::forward<_Vp>(__v)), true); } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { iterator __p = __table_.find(__k); if ( __p != end()) { __p->second = _VSTD::move(__v); return __p; } return emplace_hint(__h, __k, _VSTD::forward<_Vp>(__v)); } template _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { iterator __p = __table_.find(__k); if ( __p != end()) { __p->second = _VSTD::move(__v); return __p; } return emplace_hint(__h, _VSTD::forward(__k), _VSTD::forward<_Vp>(__v)); } #endif #endif #endif _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();} _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);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 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(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} #if _LIBCPP_DEBUG_LEVEL >= 2 bool __dereferenceable(const const_iterator* __i) const {return __table_.__dereferenceable(&__i->__i_);} bool __decrementable(const const_iterator* __i) const {return __table_.__decrementable(&__i->__i_);} bool __addable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(&__i->__i_, __n);} bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(&__i->__i_, __n);} #endif // _LIBCPP_DEBUG_LEVEL >= 2 private: #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node(); template __node_holder __construct_node(_A0&& __a0); __node_holder __construct_node_with_key(key_type&& __k); #ifndef _LIBCPP_HAS_NO_VARIADICS template __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node_with_key(const key_type& __k); }; template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); } template inline _LIBCPP_INLINE_VISIBILITY unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const allocator_type& __a) : __table_(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif insert(__first, __last); } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__first, __last); } template template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__first, __last); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u) : __table_(__u.__table_) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); __get_db()->swap(this, &__u); #endif } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( unordered_map&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) __table_.__insert_unique( _VSTD::move(__u.__table_.remove((__i++).__i_)->__value_) ); } #if _LIBCPP_DEBUG_LEVEL >= 2 else __get_db()->swap(this, &__u); #endif } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif insert(__il.begin(), __il.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY 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; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template inline _LIBCPP_INLINE_VISIBILITY unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( initializer_list __il) { __table_.__assign_unique(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node() { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(_A0&& __a0) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(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_.__cc.first), _VSTD::move(__k)); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return __h; } #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(_A0&& __a0, _A1&& __a1, _Args&&... __args) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template template pair::iterator, bool> unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::emplace(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); pair __r = __table_.__node_insert_unique(__h.get()); if (__r.second) __h.release(); return __r; } #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first), __k); __h.get_deleter().__first_constructed = true; __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second)); __h.get_deleter().__second_constructed = true; return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 } template template inline _LIBCPP_INLINE_VISIBILITY void unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_unique(*__first); } template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { iterator __i = find(__k); if (__i != end()) return __i->second; __node_holder __h = __construct_node_with_key(__k); pair __r = __table_.__node_insert_unique(__h.get()); __h.release(); return __r.first->second; } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](key_type&& __k) { iterator __i = find(__k); if (__i != end()) return __i->second; __node_holder __h = __construct_node_with_key(_VSTD::move(__k)); pair __r = __table_.__node_insert_unique(__h.get()); __h.release(); return __r.first->second; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::at(const key_type& __k) { iterator __i = find(__k); #ifndef _LIBCPP_NO_EXCEPTIONS if (__i == end()) throw out_of_range("unordered_map::at: key not found"); #endif // _LIBCPP_NO_EXCEPTIONS return __i->second; } template const _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::at(const key_type& __k) const { const_iterator __i = find(__k); #ifndef _LIBCPP_NO_EXCEPTIONS if (__i == end()) throw out_of_range("unordered_map::at: key not found"); #endif // _LIBCPP_NO_EXCEPTIONS return __i->second; } template inline _LIBCPP_INLINE_VISIBILITY void swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) { const_iterator __j = __y.find(__i->first); if (__j == __ey || !(*__i == *__j)) return false; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } template , class _Pred = equal_to<_Key>, class _Alloc = allocator > > class _LIBCPP_TYPE_VIS_ONLY unordered_multimap { public: // types typedef _Key key_type; typedef _Tp mapped_type; typedef _Hash hasher; typedef _Pred key_equal; typedef _Alloc allocator_type; typedef pair value_type; typedef pair __nc_value_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); private: typedef __hash_value_type __value_type; typedef __unordered_map_hasher __hasher; typedef __unordered_map_equal __key_equal; typedef typename __rebind_alloc_helper, __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; __table __table_; typedef typename __table::__node_traits __node_traits; typedef typename __table::__node_allocator __node_allocator; typedef typename __table::__node __node; typedef __hash_map_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; typedef allocator_traits __alloc_traits; public: typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef __hash_map_iterator iterator; typedef __hash_map_const_iterator const_iterator; typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; _LIBCPP_INLINE_VISIBILITY unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } explicit unordered_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template unordered_multimap(_InputIterator __first, _InputIterator __last); template unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); 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_HAS_NO_RVALUE_REFERENCES unordered_multimap(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); unordered_multimap(unordered_multimap&& __u, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS unordered_multimap(initializer_list __il); unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #if _LIBCPP_STD_VER > 11 _LIBCPP_INLINE_VISIBILITY unordered_multimap(size_type __n, const allocator_type& __a) : unordered_multimap(__n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__n, __hf, key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a) : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_multimap(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__il, __n, __hf, key_equal(), __a) {} #endif // ~unordered_multimap() = default; _LIBCPP_INLINE_VISIBILITY unordered_multimap& operator=(const unordered_multimap& __u) { #if __cplusplus >= 201103L __table_ = __u.__table_; #else if (this != &__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_HAS_NO_RVALUE_REFERENCES unordered_multimap& operator=(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); #endif #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS unordered_multimap& operator=(initializer_list __il); #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(__table_.__node_alloc());} _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();} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_VARIADICS template iterator emplace(_Args&&... __args); template iterator emplace_hint(const_iterator __p, _Args&&... __args); #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY iterator insert(const value_type& __x) {return __table_.__insert_multi(__x);} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template ::value>::type> _LIBCPP_INLINE_VISIBILITY iterator insert(_Pp&& __x) {return __table_.__insert_multi(_VSTD::forward<_Pp>(__x));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, const value_type& __x) {return __table_.__insert_multi(__p.__i_, __x);} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template ::value>::type> _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, _Pp&& __x) {return __table_.__insert_multi(__p.__i_, _VSTD::forward<_Pp>(__x));} #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template void insert(_InputIterator __first, _InputIterator __last); #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _LIBCPP_INLINE_VISIBILITY void insert(initializer_list __il) {insert(__il.begin(), __il.end());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS _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();} _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);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} _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(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.reserve(__n);} #if _LIBCPP_DEBUG_LEVEL >= 2 bool __dereferenceable(const const_iterator* __i) const {return __table_.__dereferenceable(&__i->__i_);} bool __decrementable(const const_iterator* __i) const {return __table_.__decrementable(&__i->__i_);} bool __addable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(&__i->__i_, __n);} bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const {return __table_.__addable(&__i->__i_, __n);} #endif // _LIBCPP_DEBUG_LEVEL >= 2 private: #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES __node_holder __construct_node(); template __node_holder __construct_node(_A0&& __a0); #ifndef _LIBCPP_HAS_NO_VARIADICS template __node_holder __construct_node(_A0&& __a0, _A1&& __a1, _Args&& ...__args); #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES }; template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif insert(__first, __last); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__first, __last); } template template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__first, __last); } template inline _LIBCPP_INLINE_VISIBILITY unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const allocator_type& __a) : __table_(__a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u) : __table_(__u.__table_) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__u.bucket_count()); insert(__u.begin(), __u.end()); } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); __get_db()->swap(this, &__u); #endif } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( unordered_multimap&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) { __table_.__insert_multi( _VSTD::move(__u.__table_.remove((__i++).__i_)->__value_) ); } } #if _LIBCPP_DEBUG_LEVEL >= 2 else __get_db()->swap(this, &__u); #endif } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif insert(__il.begin(), __il.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __table_.rehash(__n); insert(__il.begin(), __il.end()); } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template inline _LIBCPP_INLINE_VISIBILITY 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; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS template inline _LIBCPP_INLINE_VISIBILITY unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::operator=( initializer_list __il) { __table_.__assign_multi(__il.begin(), __il.end()); return *this; } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES template typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node() { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template template typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(_A0&& __a0) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0)); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } #ifndef _LIBCPP_HAS_NO_VARIADICS template template typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node( _A0&& __a0, _A1&& __a1, _Args&&... __args) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_A0>(__a0), _VSTD::forward<_A1>(__a1), _VSTD::forward<_Args>(__args)...); __h.get_deleter().__first_constructed = true; __h.get_deleter().__second_constructed = true; return __h; } template template typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::iterator unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::emplace(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __table_.__node_insert_multi(__h.get()); __h.release(); return __r; } template template typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::iterator unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::emplace_hint( const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __table_.__node_insert_multi(__p.__i_, __h.get()); __h.release(); return __r; } #endif // _LIBCPP_HAS_NO_VARIADICS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES template template inline _LIBCPP_INLINE_VISIBILITY void unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) __table_.__insert_multi(*__first); } template inline _LIBCPP_INLINE_VISIBILITY void swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } template bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { if (__x.size() != __y.size()) return false; typedef typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator; typedef pair _EqRng; for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) { _EqRng __xeq = __x.equal_range(__i->first); _EqRng __yeq = __y.equal_range(__i->first); if (_VSTD::distance(__xeq.first, __xeq.second) != _VSTD::distance(__yeq.first, __yeq.second) || !_VSTD::is_permutation(__xeq.first, __xeq.second, __yeq.first)) return false; __i = __xeq.second; } return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) { return !(__x == __y); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_UNORDERED_MAP diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py index fefbf01ad450..5ab7fcb37401 100644 --- a/test/libcxx/test/config.py +++ b/test/libcxx/test/config.py @@ -1,645 +1,646 @@ import locale import os import platform import pkgutil import re import shlex import sys import lit.Test # pylint: disable=import-error,no-name-in-module import lit.util # pylint: disable=import-error,no-name-in-module from libcxx.test.format import LibcxxTestFormat from libcxx.compiler import CXXCompiler from libcxx.test.target_info import make_target_info from libcxx.test.executor import * from libcxx.test.tracing import * def loadSiteConfig(lit_config, config, param_name, env_name): # We haven't loaded the site specific configuration (the user is # probably trying to run on a test file directly, and either the site # configuration hasn't been created by the build system, or we are in an # out-of-tree build situation). site_cfg = lit_config.params.get(param_name, os.environ.get(env_name)) if not site_cfg: lit_config.warning('No site specific configuration file found!' ' Running the tests in the default configuration.') elif not os.path.isfile(site_cfg): lit_config.fatal( "Specified site configuration file does not exist: '%s'" % site_cfg) else: lit_config.note('using site specific configuration at %s' % site_cfg) ld_fn = lit_config.load_config # Null out the load_config function so that lit.site.cfg doesn't # recursively load a config even if it tries. # TODO: This is one hell of a hack. Fix it. def prevent_reload_fn(*args, **kwargs): pass lit_config.load_config = prevent_reload_fn ld_fn(config, site_cfg) lit_config.load_config = ld_fn class Configuration(object): # pylint: disable=redefined-outer-name def __init__(self, lit_config, config): self.lit_config = lit_config self.config = config self.cxx = None self.project_obj_root = None self.libcxx_src_root = None self.libcxx_obj_root = None self.cxx_library_root = None self.abi_library_root = None self.env = {} self.use_target = False self.use_system_cxx_lib = False self.use_clang_verify = False self.long_tests = None self.execute_external = False def get_lit_conf(self, name, default=None): val = self.lit_config.params.get(name, None) if val is None: val = getattr(self.config, name, None) if val is None: val = default return val def get_lit_bool(self, name, default=None): conf = self.get_lit_conf(name) if conf is None: return default if conf.lower() in ('1', 'true'): return True if conf.lower() in ('', '0', 'false'): return False self.lit_config.fatal( "parameter '{}' should be true or false".format(name)) def configure(self): self.configure_executor() self.configure_target_info() self.configure_cxx() self.configure_triple() self.configure_src_root() self.configure_obj_root() self.configure_cxx_library_root() self.configure_use_system_cxx_lib() self.configure_use_clang_verify() self.configure_execute_external() self.configure_ccache() self.configure_compile_flags() self.configure_link_flags() self.configure_env() self.configure_color_diagnostics() self.configure_debug_mode() self.configure_warnings() self.configure_sanitizer() self.configure_coverage() self.configure_substitutions() self.configure_features() def print_config_info(self): # Print the final compile and link flags. self.lit_config.note('Using compiler: %s' % self.cxx.path) self.lit_config.note('Using flags: %s' % self.cxx.flags) self.lit_config.note('Using compile flags: %s' % self.cxx.compile_flags) self.lit_config.note('Using link flags: %s' % self.cxx.link_flags) # Print as list to prevent "set([...])" from being printed. self.lit_config.note('Using available_features: %s' % list(self.config.available_features)) self.lit_config.note('Using environment: %r' % self.env) def get_test_format(self): return LibcxxTestFormat( self.cxx, self.use_clang_verify, self.execute_external, self.executor, exec_env=self.env) def configure_executor(self): exec_str = self.get_lit_conf('executor', "None") te = eval(exec_str) if te: self.lit_config.note("Using executor: %r" % exec_str) if self.lit_config.useValgrind: # We have no way of knowing where in the chain the # ValgrindExecutor is supposed to go. It is likely # that the user wants it at the end, but we have no # way of getting at that easily. selt.lit_config.fatal("Cannot infer how to create a Valgrind " " executor.") else: te = LocalExecutor() if self.lit_config.useValgrind: te = ValgrindExecutor(self.lit_config.valgrindArgs, te) self.executor = te def configure_target_info(self): self.target_info = make_target_info(self) def configure_cxx(self): # Gather various compiler parameters. cxx = self.get_lit_conf('cxx_under_test') # If no specific cxx_under_test was given, attempt to infer it as # clang++. if cxx is None: clangxx = lit.util.which('clang++', self.config.environment['PATH']) if clangxx: cxx = clangxx self.lit_config.note( "inferred cxx_under_test as: %r" % cxx) if not cxx: self.lit_config.fatal('must specify user parameter cxx_under_test ' '(e.g., --param=cxx_under_test=clang++)') self.cxx = CXXCompiler(cxx) cxx_type = self.cxx.type if cxx_type is not None: assert self.cxx.version is not None maj_v, min_v, _ = self.cxx.version self.config.available_features.add(cxx_type) self.config.available_features.add('%s-%s.%s' % ( cxx_type, maj_v, min_v)) def configure_src_root(self): self.libcxx_src_root = self.get_lit_conf( 'libcxx_src_root', os.path.dirname(self.config.test_source_root)) def configure_obj_root(self): self.project_obj_root = self.get_lit_conf('project_obj_root') self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root') if not self.libcxx_obj_root and self.project_obj_root is not None: possible_root = os.path.join(self.project_obj_root, 'projects', 'libcxx') if os.path.isdir(possible_root): self.libcxx_obj_root = possible_root else: self.libcxx_obj_root = self.project_obj_root def configure_cxx_library_root(self): self.cxx_library_root = self.get_lit_conf('cxx_library_root', self.libcxx_obj_root) def configure_use_system_cxx_lib(self): # This test suite supports testing against either the system library or # the locally built one; the former mode is useful for testing ABI # compatibility between the current headers and a shipping dynamic # library. self.use_system_cxx_lib = self.get_lit_bool('use_system_cxx_lib') if self.use_system_cxx_lib is None: # Default to testing against the locally built libc++ library. self.use_system_cxx_lib = False self.lit_config.note( "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib) def configure_use_clang_verify(self): '''If set, run clang with -verify on failing tests.''' self.use_clang_verify = self.get_lit_bool('use_clang_verify') if self.use_clang_verify is None: # NOTE: We do not test for the -verify flag directly because # -verify will always exit with non-zero on an empty file. self.use_clang_verify = self.cxx.hasCompileFlag( ['-Xclang', '-verify-ignore-unexpected']) self.lit_config.note( "inferred use_clang_verify as: %r" % self.use_clang_verify) def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the # default value. Otherwise we ask the target_info. use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL') if use_lit_shell_default is not None: use_lit_shell_default = use_lit_shell_default != '0' else: use_lit_shell_default = self.target_info.use_lit_shell_default() # Check for the command line parameter using the default value if it is # not present. use_lit_shell = self.get_lit_bool('use_lit_shell', use_lit_shell_default) self.execute_external = not use_lit_shell def configure_ccache(self): use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None use_ccache = self.get_lit_bool('use_ccache', use_ccache_default) if use_ccache: self.cxx.use_ccache = True self.lit_config.note('enabling ccache') def configure_features(self): additional_features = self.get_lit_conf('additional_features') if additional_features: for f in additional_features.split(','): self.config.available_features.add(f.strip()) self.target_info.add_locale_features(self.config.available_features) target_platform = self.target_info.platform() # Write an "available feature" that combines the triple when # use_system_cxx_lib is enabled. This is so that we can easily write # XFAIL markers for tests that are known to fail with versions of # libc++ as were shipped with a particular triple. if self.use_system_cxx_lib: self.config.available_features.add( 'with_system_cxx_lib=%s' % self.config.target_triple) # Insert the platform name into the available features as a lower case. self.config.available_features.add(target_platform) # Simulator testing can take a really long time for some of these tests # so add a feature check so we can REQUIRES: long_tests in them self.long_tests = self.get_lit_bool('long_tests') if self.long_tests is None: # Default to running long tests. self.long_tests = True self.lit_config.note( "inferred long_tests as: %r" % self.long_tests) if self.long_tests: self.config.available_features.add('long_tests') # Run a compile test for the -fsized-deallocation flag. This is needed # in test/std/language.support/support.dynamic/new.delete if self.cxx.hasCompileFlag('-fsized-deallocation'): self.config.available_features.add('fsized-deallocation') def configure_compile_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: self.configure_default_compile_flags() # Configure extra flags compile_flags_str = self.get_lit_conf('compile_flags', '') self.cxx.compile_flags += shlex.split(compile_flags_str) def configure_default_compile_flags(self): # Try and get the std version from the command line. Fall back to # default given in lit.site.cfg is not present. If default is not # present then force c++11. std = self.get_lit_conf('std') if not std: # Choose the newest possible language dialect if none is given. possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03'] for s in possible_stds: if self.cxx.hasCompileFlag('-std=%s' % s): std = s self.lit_config.note( 'inferred language dialect as: %s' % std) break if not std: self.lit_config.fatal( 'Failed to infer a supported language dialect from one of %r' % possible_stds) self.cxx.compile_flags += ['-std={0}'.format(std)] self.config.available_features.add(std) # Configure include paths self.cxx.compile_flags += ['-nostdinc++'] self.configure_compile_flags_header_includes() self.target_info.add_cxx_compile_flags(self.cxx.compile_flags) # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() self.configure_compile_flags_abi_version() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] # Use verbose output for better errors self.cxx.flags += ['-v'] sysroot = self.get_lit_conf('sysroot') if sysroot: self.cxx.flags += ['--sysroot', sysroot] gcc_toolchain = self.get_lit_conf('gcc_toolchain') if gcc_toolchain: self.cxx.flags += ['-gcc-toolchain', gcc_toolchain] if self.use_target: self.cxx.flags += ['-target', self.config.target_triple] def configure_compile_flags_header_includes(self): support_path = os.path.join(self.libcxx_src_root, 'test/support') self.cxx.compile_flags += ['-I' + support_path] self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')] self.configure_config_site_header() libcxx_headers = self.get_lit_conf( 'libcxx_headers', os.path.join(self.libcxx_src_root, 'include')) if not os.path.isdir(libcxx_headers): self.lit_config.fatal("libcxx_headers='%s' is not a directory." % libcxx_headers) self.cxx.compile_flags += ['-I' + libcxx_headers] def configure_config_site_header(self): # Check for a possible __config_site in the build directory. We # use this if it exists. if self.libcxx_obj_root is None: return config_site_header = os.path.join(self.libcxx_obj_root, '__config_site') if not os.path.isfile(config_site_header): return contained_macros = self.parse_config_site_and_add_features( config_site_header) self.lit_config.note('Using __config_site header %s with macros: %r' % (config_site_header, contained_macros)) # FIXME: This must come after the call to # 'parse_config_site_and_add_features(...)' in order for it to work. self.cxx.compile_flags += ['-include', config_site_header] def parse_config_site_and_add_features(self, header): """ parse_config_site_and_add_features - Deduce and add the test features that that are implied by the #define's in the __config_site header. Return a dictionary containing the macros found in the '__config_site' header. """ # Parse the macro contents of __config_site by dumping the macros # using 'c++ -dM -E' and filtering the predefines. predefines = self.cxx.dumpMacros() macros = self.cxx.dumpMacros(header) feature_macros_keys = set(macros.keys()) - set(predefines.keys()) feature_macros = {} for k in feature_macros_keys: feature_macros[k] = macros[k] # We expect the header guard to be one of the definitions assert '_LIBCPP_CONFIG_SITE' in feature_macros del feature_macros['_LIBCPP_CONFIG_SITE'] # The __config_site header should be non-empty. Otherwise it should # have never been emitted by CMake. assert len(feature_macros) > 0 # Transform each macro name into the feature name used in the tests. # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads for m in feature_macros: if m == '_LIBCPP_ABI_VERSION': self.config.available_features.add('libcpp-abi-version-v%s' % feature_macros[m]) continue assert m.startswith('_LIBCPP_HAS_') or m == '_LIBCPP_ABI_UNSTABLE' m = m.lower()[1:].replace('_', '-') self.config.available_features.add(m) return feature_macros def configure_compile_flags_exceptions(self): enable_exceptions = self.get_lit_bool('enable_exceptions', True) if not enable_exceptions: self.config.available_features.add('libcpp-no-exceptions') self.cxx.compile_flags += ['-fno-exceptions'] def configure_compile_flags_rtti(self): enable_rtti = self.get_lit_bool('enable_rtti', True) if not enable_rtti: self.config.available_features.add('libcpp-no-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] def configure_compile_flags_abi_version(self): abi_version = self.get_lit_conf('abi_version', '').strip() abi_unstable = self.get_lit_bool('abi_unstable') # Only add the ABI version when it is non-default. # FIXME(EricWF): Get the ABI version from the "__config_site". if abi_version and abi_version != '1': self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] if abi_unstable: self.config.available_features.add('libcpp-abi-unstable') self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] def configure_link_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: self.cxx.link_flags += ['-nodefaultlibs'] # Configure library path self.configure_link_flags_cxx_library_path() self.configure_link_flags_abi_library_path() # Configure libraries self.configure_link_flags_cxx_library() self.configure_link_flags_abi_library() self.configure_extra_library_flags() link_flags_str = self.get_lit_conf('link_flags', '') self.cxx.link_flags += shlex.split(link_flags_str) def configure_link_flags_cxx_library_path(self): libcxx_library = self.get_lit_conf('libcxx_library') # Configure libc++ library paths. if libcxx_library is not None: # Check that the given value for libcxx_library is valid. if not os.path.isfile(libcxx_library): self.lit_config.fatal( "libcxx_library='%s' is not a valid file." % libcxx_library) if self.use_system_cxx_lib: self.lit_config.fatal( "Conflicting options: 'libcxx_library' cannot be used " "with 'use_system_cxx_lib=true'") self.cxx.link_flags += ['-Wl,-rpath,' + os.path.dirname(libcxx_library)] elif not self.use_system_cxx_lib and self.cxx_library_root: self.cxx.link_flags += ['-L' + self.cxx_library_root, '-Wl,-rpath,' + self.cxx_library_root] def configure_link_flags_abi_library_path(self): # Configure ABI library paths. self.abi_library_root = self.get_lit_conf('abi_library_path') if self.abi_library_root: self.cxx.link_flags += ['-L' + self.abi_library_root, '-Wl,-rpath,' + self.abi_library_root] def configure_link_flags_cxx_library(self): libcxx_library = self.get_lit_conf('libcxx_library') if libcxx_library: self.cxx.link_flags += [libcxx_library] else: self.cxx.link_flags += ['-lc++'] def configure_link_flags_abi_library(self): cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi') if cxx_abi == 'libstdc++': self.cxx.link_flags += ['-lstdc++'] elif cxx_abi == 'libsupc++': self.cxx.link_flags += ['-lsupc++'] elif cxx_abi == 'libcxxabi': if self.target_info.allow_cxxabi_link(): self.cxx.link_flags += ['-lc++abi'] elif cxx_abi == 'libcxxrt': self.cxx.link_flags += ['-lcxxrt'] elif cxx_abi == 'none': pass else: self.lit_config.fatal( 'C++ ABI setting %s unsupported for tests' % cxx_abi) def configure_extra_library_flags(self): self.target_info.add_cxx_link_flags(self.cxx.link_flags) def configure_color_diagnostics(self): use_color = self.get_lit_conf('color_diagnostics') if use_color is None: use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS') if use_color is None: return if use_color != '': self.lit_config.fatal('Invalid value for color_diagnostics "%s".' % use_color) color_flag = '-fdiagnostics-color=always' # Check if the compiler supports the color diagnostics flag. Issue a # warning if it does not since color diagnostics have been requested. if not self.cxx.hasCompileFlag(color_flag): self.lit_config.warning( 'color diagnostics have been requested but are not supported ' 'by the compiler') else: self.cxx.flags += [color_flag] def configure_debug_mode(self): debug_level = self.get_lit_conf('debug_level', None) if not debug_level: return if debug_level not in ['0', '1']: self.lit_config.fatal('Invalid value for debug_level "%s".' % debug_level) self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level] def configure_warnings(self): enable_warnings = self.get_lit_bool('enable_warnings', False) if enable_warnings: self.cxx.compile_flags += [ '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Werror' ] self.cxx.addWarningFlagIfSupported('-Wno-attributes') self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move') self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions') self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals') # TODO(EricWF) Remove the unused warnings once the test suite # compiles clean with them. self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') self.cxx.addWarningFlagIfSupported('-Wno-unused-variable') std = self.get_lit_conf('std', None) if std in ['c++98', 'c++03']: # The '#define static_assert' provided by libc++ in C++03 mode # causes an unused local typedef whenever it is used. self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') def configure_sanitizer(self): san = self.get_lit_conf('use_sanitizer', '').strip() if san: self.target_info.add_sanitizer_features(san, self.config.available_features) # Search for llvm-symbolizer along the compiler path first # and then along the PATH env variable. symbolizer_search_paths = os.environ.get('PATH', '') cxx_path = lit.util.which(self.cxx.path) if cxx_path is not None: symbolizer_search_paths = ( os.path.dirname(cxx_path) + os.pathsep + symbolizer_search_paths) llvm_symbolizer = lit.util.which('llvm-symbolizer', symbolizer_search_paths) # Setup the sanitizer compile flags self.cxx.flags += ['-g', '-fno-omit-frame-pointer'] if san == 'Address': self.cxx.flags += ['-fsanitize=address'] if llvm_symbolizer is not None: self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer self.config.available_features.add('asan') self.config.available_features.add('sanitizer-new-delete') elif san == 'Memory' or san == 'MemoryWithOrigins': self.cxx.flags += ['-fsanitize=memory'] if san == 'MemoryWithOrigins': self.cxx.compile_flags += [ '-fsanitize-memory-track-origins'] if llvm_symbolizer is not None: self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer self.config.available_features.add('msan') self.config.available_features.add('sanitizer-new-delete') elif san == 'Undefined': self.cxx.flags += ['-fsanitize=undefined', '-fno-sanitize=vptr,function', '-fno-sanitize-recover'] self.cxx.compile_flags += ['-O3'] + self.env['UBSAN_OPTIONS'] = 'print_stacktrace=1' self.config.available_features.add('ubsan') elif san == 'Thread': self.cxx.flags += ['-fsanitize=thread'] self.config.available_features.add('tsan') self.config.available_features.add('sanitizer-new-delete') else: self.lit_config.fatal('unsupported value for ' 'use_sanitizer: {0}'.format(san)) san_lib = self.get_lit_conf('sanitizer_library') if san_lib: self.cxx.link_flags += [ san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)] def configure_coverage(self): self.generate_coverage = self.get_lit_bool('generate_coverage', False) if self.generate_coverage: self.cxx.flags += ['-g', '--coverage'] self.cxx.compile_flags += ['-O0'] def configure_substitutions(self): sub = self.config.substitutions # Configure compiler substitions sub.append(('%cxx', self.cxx.path)) # Configure flags substitutions flags_str = ' '.join(self.cxx.flags) compile_flags_str = ' '.join(self.cxx.compile_flags) link_flags_str = ' '.join(self.cxx.link_flags) all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str) sub.append(('%flags', flags_str)) sub.append(('%compile_flags', compile_flags_str)) sub.append(('%link_flags', link_flags_str)) sub.append(('%all_flags', all_flags)) # Add compile and link shortcuts compile_str = (self.cxx.path + ' -o %t.o %s -c ' + flags_str + compile_flags_str) link_str = (self.cxx.path + ' -o %t.exe %t.o ' + flags_str + link_flags_str) assert type(link_str) is str build_str = self.cxx.path + ' -o %t.exe %s ' + all_flags sub.append(('%compile', compile_str)) sub.append(('%link', link_str)) sub.append(('%build', build_str)) # Configure exec prefix substitutions. exec_env_str = 'env ' if len(self.env) != 0 else '' for k, v in self.env.items(): exec_env_str += ' %s=%s' % (k, v) # Configure run env substitution. exec_str = '' if self.lit_config.useValgrind: exec_str = ' '.join(self.lit_config.valgrindArgs) + exec_env_str sub.append(('%exec', exec_str)) # Configure run shortcut sub.append(('%run', exec_str + ' %t.exe')) # Configure not program substitions not_py = os.path.join(self.libcxx_src_root, 'utils', 'not', 'not.py') not_str = '%s %s' % (sys.executable, not_py) sub.append(('not', not_str)) def configure_triple(self): # Get or infer the target triple. self.config.target_triple = self.get_lit_conf('target_triple') self.use_target = bool(self.config.target_triple) # If no target triple was given, try to infer it from the compiler # under test. if not self.use_target: target_triple = self.cxx.getTriple() # Drop sub-major version components from the triple, because the # current XFAIL handling expects exact matches for feature checks. # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14 # The 5th group handles triples greater than 3 parts # (ex x86_64-pc-linux-gnu). target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)', r'\1-\2-\3\5', target_triple) # linux-gnu is needed in the triple to properly identify linuxes # that use GLIBC. Handle redhat and opensuse triples as special # cases and append the missing `-gnu` portion. if (target_triple.endswith('redhat-linux') or target_triple.endswith('suse-linux')): target_triple += '-gnu' self.config.target_triple = target_triple self.lit_config.note( "inferred target_triple as: %r" % self.config.target_triple) def configure_env(self): self.target_info.configure_env(self.env) diff --git a/test/libcxx/test/target_info.py b/test/libcxx/test/target_info.py index 667644d2fec6..df216fcb21fa 100644 --- a/test/libcxx/test/target_info.py +++ b/test/libcxx/test/target_info.py @@ -1,202 +1,202 @@ import importlib import lit.util # pylint: disable=import-error,no-name-in-module import locale import os import platform import sys class DefaultTargetInfo(object): def __init__(self, full_config): self.full_config = full_config def platform(self): return sys.platform.lower().strip() def add_locale_features(self, features): self.full_config.lit_config.warning( "No locales entry for target_system: %s" % self.platform()) def add_cxx_compile_flags(self, flags): pass def add_cxx_link_flags(self, flags): pass def configure_env(self, env): pass def allow_cxxabi_link(self): return True def add_sanitizer_features(self, sanitizer_type, features): pass def use_lit_shell_default(self): return False def test_locale(loc): assert loc is not None default_locale = locale.setlocale(locale.LC_ALL) try: locale.setlocale(locale.LC_ALL, loc) return True except locale.Error: return False finally: locale.setlocale(locale.LC_ALL, default_locale) def add_common_locales(features, lit_config): # A list of locales needed by the test-suite. # The list uses the canonical name for the locale used in the test-suite # TODO: On Linux ISO8859 *may* needs to hyphenated. locales = [ 'en_US.UTF-8', 'fr_FR.UTF-8', 'ru_RU.UTF-8', 'zh_CN.UTF-8', 'fr_CA.ISO8859-1', 'cs_CZ.ISO8859-2' ] for loc in locales: if test_locale(loc): features.add('locale.{0}'.format(loc)) else: lit_config.warning('The locale {0} is not supported by ' 'your platform. Some tests will be ' 'unsupported.'.format(loc)) class DarwinLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(DarwinLocalTI, self).__init__(full_config) def add_locale_features(self, features): - add_common_locales(feature, self.full_config.lit_config) + add_common_locales(features, self.full_config.lit_config) def add_cxx_compile_flags(self, flags): try: out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() res = 0 except OSError: res = -1 if res == 0 and out: sdk_path = out self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) flags += ["-isysroot", sdk_path] def add_cxx_link_flags(self, flags): flags += ['-lSystem'] def configure_env(self, env): library_paths = [] # Configure the library path for libc++ libcxx_library = self.full_config.get_lit_conf('libcxx_library') if self.full_config.use_system_cxx_lib: pass elif libcxx_library: library_paths += [os.path.dirname(libcxx_library)] elif self.full_config.cxx_library_root: library_paths += [self.full_config.cxx_library_root] # Configure the abi library path if self.full_config.abi_library_root: library_paths += [self.full_config.abi_library_root] if library_paths: env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths) def allow_cxxabi_link(self): # Don't link libc++abi explicitly on OS X because the symbols # should be available in libc++ directly. return False def add_sanitizer_features(self, sanitizer_type, features): if san == 'Undefined': features.add('sanitizer-new-delete') class FreeBSDLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(FreeBSDLocalTI, self).__init__(full_config) def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) def add_cxx_link_flags(self, flags): flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] class LinuxLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(LinuxLocalTI, self).__init__(full_config) def platform(self): return 'linux' def platform_name(self): name, _, _ = platform.linux_distribution() name = name.lower().strip() return name # Permitted to be None def platform_ver(self): _, ver, _ = platform.linux_distribution() ver = ver.lower().strip() return ver # Permitted to be None. def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) # Some linux distributions have different locale data than others. # Insert the distributions name and name-version into the available # features to allow tests to XFAIL on them. name = self.platform_name() ver = self.platform_ver() if name: features.add(name) if name and ver: features.add('%s-%s' % (name, ver)) def add_cxx_compile_flags(self, flags): flags += ['-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS'] def add_cxx_link_flags(self, flags): enable_threads = ('libcpp-has-no-threads' not in self.full_config.config.available_features) llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False) flags += ['-lm'] if not llvm_unwinder: flags += ['-lgcc_s', '-lgcc'] if enable_threads: flags += ['-lpthread'] flags += ['-lc'] if llvm_unwinder: flags += ['-lunwind', '-ldl'] else: flags += ['-lgcc_s', '-lgcc'] san = self.full_config.get_lit_conf('use_sanitizer', '').strip() if san: # The libraries and their order are taken from the # linkSanitizerRuntimeDeps function in # clang/lib/Driver/Tools.cpp flags += ['-lpthread', '-lrt', '-lm', '-ldl'] class WindowsLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(WindowsLocalTI, self).__init__(full_config) def add_locale_features(self, features): add_common_locales(features, self.full_config.lit_config) def use_lit_shell_default(self): # Default to the internal shell on Windows, as bash on Windows is # usually very slow. return True def make_target_info(full_config): default = "libcxx.test.target_info.LocalTI" info_str = full_config.get_lit_conf('target_info', default) if info_str != default: mod_path, _, info = info_str.rpartition('.') mod = importlib.import_module(mod_path) target_info = getattr(mod, info)(full_config) full_config.lit_config.note("inferred target_info as: %r" % info_str) return target_info target_system = platform.system() if target_system == 'Darwin': return DarwinLocalTI(full_config) if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config) if target_system == 'Linux': return LinuxLocalTI(full_config) if target_system == 'Windows': return WindowsLocalTI(full_config) return DefaultTargetInfo(full_config) diff --git a/test/std/containers/associative/map/map.modifiers/insert_iter_rv.pass.cpp b/test/std/containers/associative/map/map.modifiers/insert_iter_rv.pass.cpp index 42b41fd7b867..9db1e5c70732 100644 --- a/test/std/containers/associative/map/map.modifiers/insert_iter_rv.pass.cpp +++ b/test/std/containers/associative/map/map.modifiers/insert_iter_rv.pass.cpp @@ -1,87 +1,118 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // class map // template // iterator insert(const_iterator position, P&& p); #include #include #include "MoveOnly.h" #include "min_allocator.h" +#include "test_macros.h" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::map M; typedef std::pair P; typedef M::iterator R; M m; R r = m.insert(m.end(), P(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(m.end(), P(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(m.end(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(m.end(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); } -#if __cplusplus >= 201103L +#if TEST_STD_VER >= 11 { typedef std::map, min_allocator>> M; typedef std::pair P; typedef M::iterator R; M m; R r = m.insert(m.end(), P(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(m.end(), P(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(m.end(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(m.end(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); } #endif +#if TEST_STD_VER > 14 + { + typedef std::map M; + typedef M::iterator R; + M m; + R r = m.insert(m.end(), {2, MoveOnly(2)}); + assert(r == m.begin()); + assert(m.size() == 1); + assert(r->first == 2); + assert(r->second == 2); + + r = m.insert(m.end(), {1, MoveOnly(1)}); + assert(r == m.begin()); + assert(m.size() == 2); + assert(r->first == 1); + assert(r->second == 1); + + r = m.insert(m.end(), {3, MoveOnly(3)}); + assert(r == prev(m.end())); + assert(m.size() == 3); + assert(r->first == 3); + assert(r->second == 3); + + r = m.insert(m.end(), {3, MoveOnly(3)}); + assert(r == prev(m.end())); + assert(m.size() == 3); + assert(r->first == 3); + assert(r->second == 3); + } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif } diff --git a/test/std/containers/associative/map/map.modifiers/insert_rv.pass.cpp b/test/std/containers/associative/map/map.modifiers/insert_rv.pass.cpp index a9d3277e6d94..23eb84d687ff 100644 --- a/test/std/containers/associative/map/map.modifiers/insert_rv.pass.cpp +++ b/test/std/containers/associative/map/map.modifiers/insert_rv.pass.cpp @@ -1,93 +1,129 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // class map +// pair insert( value_type&& v); // C++17 and later // template // pair insert(P&& p); #include #include #include "MoveOnly.h" #include "min_allocator.h" +#include "test_macros.h" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::map M; typedef std::pair R; M m; R r = m.insert(M::value_type(2, 2)); assert(r.second); assert(r.first == m.begin()); assert(m.size() == 1); assert(r.first->first == 2); assert(r.first->second == 2); r = m.insert(M::value_type(1, 1)); assert(r.second); assert(r.first == m.begin()); assert(m.size() == 2); assert(r.first->first == 1); assert(r.first->second == 1); r = m.insert(M::value_type(3, 3)); assert(r.second); assert(r.first == prev(m.end())); assert(m.size() == 3); assert(r.first->first == 3); assert(r.first->second == 3); r = m.insert(M::value_type(3, 3)); assert(!r.second); assert(r.first == prev(m.end())); assert(m.size() == 3); assert(r.first->first == 3); assert(r.first->second == 3); } -#if __cplusplus >= 201103L +#if TEST_STD_VER >= 11 { typedef std::map, min_allocator>> M; typedef std::pair R; M m; R r = m.insert(M::value_type(2, 2)); assert(r.second); assert(r.first == m.begin()); assert(m.size() == 1); assert(r.first->first == 2); assert(r.first->second == 2); r = m.insert(M::value_type(1, 1)); assert(r.second); assert(r.first == m.begin()); assert(m.size() == 2); assert(r.first->first == 1); assert(r.first->second == 1); r = m.insert(M::value_type(3, 3)); assert(r.second); assert(r.first == prev(m.end())); assert(m.size() == 3); assert(r.first->first == 3); assert(r.first->second == 3); r = m.insert(M::value_type(3, 3)); assert(!r.second); assert(r.first == prev(m.end())); assert(m.size() == 3); assert(r.first->first == 3); assert(r.first->second == 3); } #endif +#if TEST_STD_VER > 14 + { + typedef std::map M; + typedef std::pair R; + M m; + R r = m.insert({2, MoveOnly(2)}); + assert(r.second); + assert(r.first == m.begin()); + assert(m.size() == 1); + assert(r.first->first == 2); + assert(r.first->second == 2); + + r = m.insert({1, MoveOnly(1)}); + assert(r.second); + assert(r.first == m.begin()); + assert(m.size() == 2); + assert(r.first->first == 1); + assert(r.first->second == 1); + + r = m.insert({3, MoveOnly(3)}); + assert(r.second); + assert(r.first == prev(m.end())); + assert(m.size() == 3); + assert(r.first->first == 3); + assert(r.first->second == 3); + + r = m.insert({3, MoveOnly(3)}); + assert(!r.second); + assert(r.first == prev(m.end())); + assert(m.size() == 3); + assert(r.first->first == 3); + assert(r.first->second == 3); + } +#endif #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/containers/associative/multimap/multimap.modifiers/insert_iter_rv.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/insert_iter_rv.pass.cpp index b44f46429ec8..7035de83f990 100644 --- a/test/std/containers/associative/multimap/multimap.modifiers/insert_iter_rv.pass.cpp +++ b/test/std/containers/associative/multimap/multimap.modifiers/insert_iter_rv.pass.cpp @@ -1,87 +1,119 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // class multimap // template // iterator insert(const_iterator position, P&& p); #include #include #include "MoveOnly.h" #include "min_allocator.h" +#include "test_macros.h" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::multimap M; typedef std::pair P; typedef M::iterator R; M m; R r = m.insert(m.cend(), P(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(m.cend(), P(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(m.cend(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(m.cend(), P(3, 2)); assert(r == prev(m.end())); assert(m.size() == 4); assert(r->first == 3); assert(r->second == 2); } -#if __cplusplus >= 201103L +#if TEST_STD_VER >= 11 { typedef std::multimap, min_allocator>> M; typedef std::pair P; typedef M::iterator R; M m; R r = m.insert(m.cend(), P(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(m.cend(), P(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(m.cend(), P(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(m.cend(), P(3, 2)); assert(r == prev(m.end())); assert(m.size() == 4); assert(r->first == 3); assert(r->second == 2); } #endif +#if TEST_STD_VER > 14 + { + typedef std::multimap M; + typedef std::pair P; + typedef M::iterator R; + M m; + R r = m.insert(m.cend(), {2, MoveOnly(2)}); + assert(r == m.begin()); + assert(m.size() == 1); + assert(r->first == 2); + assert(r->second == 2); + + r = m.insert(m.cend(), {1, MoveOnly(1)}); + assert(r == m.begin()); + assert(m.size() == 2); + assert(r->first == 1); + assert(r->second == 1); + + r = m.insert(m.cend(), {3, MoveOnly(3)}); + assert(r == prev(m.end())); + assert(m.size() == 3); + assert(r->first == 3); + assert(r->second == 3); + + r = m.insert(m.cend(), {3, MoveOnly(2)}); + assert(r == prev(m.end())); + assert(m.size() == 4); + assert(r->first == 3); + assert(r->second == 2); + } +#endif #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/std/containers/associative/multimap/multimap.modifiers/insert_rv.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/insert_rv.pass.cpp index b1c043586d65..825e304f65a8 100644 --- a/test/std/containers/associative/multimap/multimap.modifiers/insert_rv.pass.cpp +++ b/test/std/containers/associative/multimap/multimap.modifiers/insert_rv.pass.cpp @@ -1,85 +1,116 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // class multimap // template // iterator insert(P&& p); #include #include #include "MoveOnly.h" #include "min_allocator.h" +#include "test_macros.h" int main() { #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES { typedef std::multimap M; typedef M::iterator R; M m; R r = m.insert(M::value_type(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(M::value_type(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(M::value_type(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(M::value_type(3, 3)); assert(r == prev(m.end())); assert(m.size() == 4); assert(r->first == 3); assert(r->second == 3); } -#if __cplusplus >= 201103L +#if TEST_STD_VER >= 11 { typedef std::multimap, min_allocator>> M; typedef M::iterator R; M m; R r = m.insert(M::value_type(2, 2)); assert(r == m.begin()); assert(m.size() == 1); assert(r->first == 2); assert(r->second == 2); r = m.insert(M::value_type(1, 1)); assert(r == m.begin()); assert(m.size() == 2); assert(r->first == 1); assert(r->second == 1); r = m.insert(M::value_type(3, 3)); assert(r == prev(m.end())); assert(m.size() == 3); assert(r->first == 3); assert(r->second == 3); r = m.insert(M::value_type(3, 3)); assert(r == prev(m.end())); assert(m.size() == 4); assert(r->first == 3); assert(r->second == 3); } #endif +#if TEST_STD_VER > 14 + { + typedef std::multimap M; + typedef M::iterator R; + M m; + R r = m.insert({2, MoveOnly(2)}); + assert(r == m.begin()); + assert(m.size() == 1); + assert(r->first == 2); + assert(r->second == 2); + + r = m.insert({1, MoveOnly(1)}); + assert(r == m.begin()); + assert(m.size() == 2); + assert(r->first == 1); + assert(r->second == 1); + + r = m.insert({3, MoveOnly(3)}); + assert(r == prev(m.end())); + assert(m.size() == 3); + assert(r->first == 3); + assert(r->second == 3); + + r = m.insert({3, MoveOnly(3)}); + assert(r == prev(m.end())); + assert(m.size() == 4); + assert(r->first == 3); + assert(r->second == 3); + } +#endif #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES } diff --git a/test/support/MoveOnly.h b/test/support/MoveOnly.h index e4d9f6495602..ee6ae7c7e5f9 100644 --- a/test/support/MoveOnly.h +++ b/test/support/MoveOnly.h @@ -1,50 +1,51 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MOVEONLY_H #define MOVEONLY_H #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #include #include class MoveOnly { + friend class MoveOnly2; MoveOnly(const MoveOnly&); MoveOnly& operator=(const MoveOnly&); int data_; public: MoveOnly(int data = 1) : data_(data) {} MoveOnly(MoveOnly&& x) : data_(x.data_) {x.data_ = 0;} MoveOnly& operator=(MoveOnly&& x) {data_ = x.data_; x.data_ = 0; return *this;} int get() const {return data_;} bool operator==(const MoveOnly& x) const {return data_ == x.data_;} bool operator< (const MoveOnly& x) const {return data_ < x.data_;} }; namespace std { template <> struct hash : public std::unary_function { std::size_t operator()(const MoveOnly& x) const {return x.get();} }; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #endif // MOVEONLY_H