Index: projects/clang390-import/contrib/libc++/CREDITS.TXT =================================================================== --- projects/clang390-import/contrib/libc++/CREDITS.TXT (revision 305075) +++ projects/clang390-import/contrib/libc++/CREDITS.TXT (revision 305076) @@ -1,138 +1,142 @@ This file is a partial list of people who have contributed to the LLVM/libc++ project. If you have contributed a patch or made some other contribution to LLVM/libc++, please submit a patch to this file to add yourself, and it will be done! The list is sorted by surname and formatted to allow easy grepping and beautification by scripts. The fields are: name (N), email (E), web-address (W), PGP key ID and fingerprint (P), description (D), and snail-mail address (S). N: Saleem Abdulrasool E: compnerd@compnerd.org D: Minor patches and Linux fixes. N: Dan Albert E: danalbert@google.com D: Android support and test runner improvements. N: Dimitry Andric E: dimitry@andric.com D: Visibility fixes, minor FreeBSD portability patches. N: Holger Arnold E: holgerar@gmail.com D: Minor fix. N: Ruben Van Boxem E: vanboxem dot ruben at gmail dot com D: Initial Windows patches. N: David Chisnall E: theraven at theravensnest dot org D: FreeBSD and Solaris ports, libcxxrt support, some atomics work. N: Marshall Clow E: mclow.lists@gmail.com E: marshall@idio.com D: C++14 support, patches and bug fixes. +N: Jonathan B Coe +E: jbcoe@me.com +D: Implementation of propagate_const. + N: Eric Fiselier E: eric@efcs.ca D: LFTS support, patches and bug fixes. N: Bill Fisher E: william.w.fisher@gmail.com D: Regex bug fixes. N: Matthew Dempsky E: matthew@dempsky.org D: Minor patches and bug fixes. N: Google Inc. D: Copyright owner and contributor of the CityHash algorithm N: Howard Hinnant E: hhinnant@apple.com D: Architect and primary author of libc++ N: Hyeon-bin Jeong E: tuhertz@gmail.com D: Minor patches and bug fixes. N: Argyrios Kyrtzidis E: kyrtzidis@apple.com D: Bug fixes. N: Bruce Mitchener, Jr. E: bruce.mitchener@gmail.com D: Emscripten-related changes. N: Michel Morin E: mimomorin@gmail.com D: Minor patches to is_convertible. N: Andrew Morrow E: andrew.c.morrow@gmail.com D: Minor patches and Linux fixes. N: Arvid Picciani E: aep at exys dot org D: Minor patches and musl port. N: Bjorn Reese E: breese@users.sourceforge.net D: Initial regex prototype N: Nico Rieck E: nico.rieck@gmail.com D: Windows fixes N: Jon Roelofs E: jonathan@codesourcery.com D: Remote testing, Newlib port, baremetal/single-threaded support. N: Jonathan Sauer D: Minor patches, mostly related to constexpr N: Craig Silverstein E: csilvers@google.com D: Implemented Cityhash as the string hash function on 64-bit machines N: Richard Smith D: Minor patches. N: Joerg Sonnenberger E: joerg@NetBSD.org D: NetBSD port. N: Stephan Tolksdorf E: st@quanttec.com D: Minor fix N: Michael van der Westhuizen E: r1mikey at gmail dot com N: Larisse Voufo D: Minor patches. N: Klaas de Vries E: klaas at klaasgaaf dot nl D: Minor bug fix. N: Zhang Xiongpang E: zhangxiongpang@gmail.com D: Minor patches and bug fixes. N: Xing Xue E: xingxue@ca.ibm.com D: AIX port N: Zhihao Yuan E: lichray@gmail.com D: Standard compatibility fixes. N: Jeffrey Yasskin E: jyasskin@gmail.com E: jyasskin@google.com D: Linux fixes. Index: projects/clang390-import/contrib/libc++/LICENSE.TXT =================================================================== --- projects/clang390-import/contrib/libc++/LICENSE.TXT (revision 305075) +++ projects/clang390-import/contrib/libc++/LICENSE.TXT (revision 305076) @@ -1,76 +1,76 @@ ============================================================================== libc++ License ============================================================================== The libc++ library is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both. Full text of the relevant licenses is included below. ============================================================================== University of Illinois/NCSA Open Source License -Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Index: projects/clang390-import/contrib/libc++/include/__bsd_locale_defaults.h =================================================================== --- projects/clang390-import/contrib/libc++/include/__bsd_locale_defaults.h (nonexistent) +++ projects/clang390-import/contrib/libc++/include/__bsd_locale_defaults.h (revision 305076) @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===---------------------- __bsd_locale_defaults.h -----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. We don't want to define those symbols +// on other platforms though, for fear of conflicts with user code. So here, +// we will define the mapping from an internal macro to the real BSD symbol. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H +#define _LIBCPP_BSD_LOCALE_DEFAULTS_H + +#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc) +#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc) +#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc) +#define __libcpp_wcsnrtombs_l(dst, src, nwc, len, ps, loc) wcsnrtombs_l(dst, src, nwc, len, ps, loc) +#define __libcpp_wcrtomb_l(src, wc, ps, loc) wcrtomb_l(src, wc, ps, loc) +#define __libcpp_mbsnrtowcs_l(dst, src, nms, len, ps, loc) mbsnrtowcs_l(dst, src, nms, len, ps, loc) +#define __libcpp_mbrtowc_l(pwc, s, n, ps, l) mbrtowc_l(pwc, s, n, ps, l) +#define __libcpp_mbtowc_l(pwc, pmb, max, l) mbtowc_l(pwc, pmb, max, l) +#define __libcpp_mbrlen_l(s, n, ps, l) mbrlen_l(s, n, ps, l) +#define __libcpp_localeconv_l(l) localeconv_l(l) +#define __libcpp_mbsrtowcs_l(dest, src, len, ps, l) mbsrtowcs_l(dest, src, len, ps, l) +#define __libcpp_snprintf_l(...) snprintf_l(__VA_ARGS__) +#define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__) +#define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__) + +#endif // _LIBCPP_BSD_LOCALE_DEFAULTS_H Property changes on: projects/clang390-import/contrib/libc++/include/__bsd_locale_defaults.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/libc++/include/__bsd_locale_fallbacks.h =================================================================== --- projects/clang390-import/contrib/libc++/include/__bsd_locale_fallbacks.h (nonexistent) +++ projects/clang390-import/contrib/libc++/include/__bsd_locale_fallbacks.h (revision 305076) @@ -0,0 +1,138 @@ +// -*- C++ -*- +//===---------------------- __bsd_locale_fallbacks.h ----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. This file provides reimplementations +// of those functions for non-BSD platforms. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H +#define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H + +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +typedef _VSTD::remove_pointer::type __use_locale_struct; +typedef _VSTD::unique_ptr<__use_locale_struct, decltype(&uselocale)> __locale_raii; + +inline _LIBCPP_ALWAYS_INLINE +decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return MB_CUR_MAX; +} + +inline _LIBCPP_ALWAYS_INLINE +wint_t __libcpp_btowc_l(int __c, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return btowc(__c); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_wctob_l(wint_t __c, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wctob(__c); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wcsnrtombs(__dest, __src, __nwc, __len, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wcrtomb(__s, __wc, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbsnrtowcs(__dest, __src, __nms, __len, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, + mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbrtowc(__pwc, __s, __n, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbtowc(__pwc, __pmb, __max); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbrlen(__s, __n, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +lconv *__libcpp_localeconv_l(locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return localeconv(); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, + mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbsrtowcs(__dest, __src, __len, __ps); +} + +inline +int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vsnprintf(__s, __n, __format, __va); + va_end(__va); + return __res; +} + +inline +int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vasprintf(__s, __format, __va); + va_end(__va); + return __res; +} + +inline +int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vsscanf(__s, __format, __va); + va_end(__va); + return __res; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H Property changes on: projects/clang390-import/contrib/libc++/include/__bsd_locale_fallbacks.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/clang390-import/contrib/libc++/include/__config =================================================================== --- projects/clang390-import/contrib/libc++/include/__config (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__config (revision 305076) @@ -1,847 +1,904 @@ // -*- 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 +#define _LIBCPP_VERSION 3900 #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 +// Fix undefined behavior in how __tree stores its end and parent nodes. +#define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +#define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB +#define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD +#elif _LIBCPP_ABI_VERSION == 1 +// Feature macros for disabling pre ABI v1 features. All of these options +// are deprecated. +#if defined(__FreeBSD__) +#define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR #endif +#endif +#ifdef _LIBCPP_TRIVIAL_PAIR_COPY_CTOR +#error "_LIBCPP_TRIVIAL_PAIR_COPY_CTOR" is no longer supported. \ + use _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR instead +#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) +#if __has_attribute(__no_sanitize__) +#define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) +#else +#define _LIBCPP_NO_CFI +#endif + #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_PREFERRED_OVERLOAD +# if __has_attribute(__enable_if__) +# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, ""))) +# 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)) +#if !(__has_feature(cxx_exceptions)) && !defined(_LIBCPP_NO_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 // Allow for build-time disabling of unsigned integer sanitization -#ifndef _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK -#define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute((no_sanitize("unsigned-integer-overflow"))) +#if !defined(_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK) && __has_attribute(no_sanitize) +#define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) #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_TEMPLATE_ALIASES #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 +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #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 _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#define _LIBCPP_EQUAL_DELETE +#else +#define _LIBCPP_EQUAL_DELETE = delete +#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__) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +// Most unix variants have catopen. These are the specific ones that don't. +#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(_NEWLIB_VERSION) #define _LIBCPP_HAS_CATOPEN 1 #endif +#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 -# if defined(__FreeBSD__) -// Making the std::pair copy constructor trivial breaks ABI compatibility with -// earlier versions of libc++ shipped by FreeBSD, so turn it off by default. -// See also http://svnweb.freebsd.org/changeset/base/261801 -# define _LIBCPP_TRIVIAL_PAIR_COPY_CTOR 0 -# else -# define _LIBCPP_TRIVIAL_PAIR_COPY_CTOR 1 -# endif -#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 +# define _LIBCPP_STD_VER 16 // 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 +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#define _LIBCPP_CONSTEXPR_AFTER_CXX14 constexpr +#else +#define _LIBCPP_CONSTEXPR_AFTER_CXX14 +#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 +// Thread API +#if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# if defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__linux__) || \ + defined(__APPLE__) || \ + defined(__CloudABI__) || \ + defined(__sun__) +# define _LIBCPP_HAS_THREAD_API_PTHREAD +# else +# error "No thread API" +# endif // _LIBCPP_HAS_THREAD_API +#endif // _LIBCPP_HAS_NO_THREADS + +#if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# error _LIBCPP_HAS_THREAD_API_PTHREAD may only be defined when \ + _LIBCPP_HAS_NO_THREADS is not defined. +#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 #ifndef _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK #define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK -#endif +#endif + +#if __cplusplus < 201103L +#define _LIBCPP_CXX03_LANG +#else +#if defined(_LIBCPP_HAS_NO_VARIADIC_TEMPLATES) || defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) +#error Libc++ requires a feature complete C++11 compiler in C++11 or greater. +#endif +#endif + +#if (defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) \ + && __has_attribute(acquire_capability)) +#define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +#endif #endif // __cplusplus #endif // _LIBCPP_CONFIG Index: projects/clang390-import/contrib/libc++/include/__functional_base =================================================================== --- projects/clang390-import/contrib/libc++/include/__functional_base (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__functional_base (revision 305076) @@ -1,742 +1,680 @@ // -*- 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_FUNCTIONAL_BASE #define _LIBCPP_FUNCTIONAL_BASE #include <__config> #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template struct _LIBCPP_TYPE_VIS_ONLY unary_function { typedef _Arg argument_type; typedef _Result result_type; }; template struct _LIBCPP_TYPE_VIS_ONLY binary_function { typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; }; -template struct _LIBCPP_TYPE_VIS_ONLY hash; - template struct __has_result_type { private: struct __two {char __lx; char __lxx;}; template static __two __test(...); template static char __test(typename _Up::result_type* = 0); public: static const bool value = sizeof(__test<_Tp>(0)) == 1; }; #if _LIBCPP_STD_VER > 11 template #else template #endif struct _LIBCPP_TYPE_VIS_ONLY less : binary_function<_Tp, _Tp, bool> { _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const {return __x < __y;} }; #if _LIBCPP_STD_VER > 11 template <> struct _LIBCPP_TYPE_VIS_ONLY less { template _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY auto operator()(_T1&& __t, _T2&& __u) const _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) -> decltype (_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } typedef void is_transparent; }; #endif // __weak_result_type template struct __derives_from_unary_function { private: struct __two {char __lx; char __lxx;}; static __two __test(...); template static unary_function<_Ap, _Rp> __test(const volatile unary_function<_Ap, _Rp>*); public: static const bool value = !is_same::value; typedef decltype(__test((_Tp*)0)) type; }; template struct __derives_from_binary_function { private: struct __two {char __lx; char __lxx;}; static __two __test(...); template static binary_function<_A1, _A2, _Rp> __test(const volatile binary_function<_A1, _A2, _Rp>*); public: static const bool value = !is_same::value; typedef decltype(__test((_Tp*)0)) type; }; template ::value> struct __maybe_derive_from_unary_function // bool is true : public __derives_from_unary_function<_Tp>::type { }; template struct __maybe_derive_from_unary_function<_Tp, false> { }; template ::value> struct __maybe_derive_from_binary_function // bool is true : public __derives_from_binary_function<_Tp>::type { }; template struct __maybe_derive_from_binary_function<_Tp, false> { }; template ::value> struct __weak_result_type_imp // bool is true : public __maybe_derive_from_unary_function<_Tp>, public __maybe_derive_from_binary_function<_Tp> { typedef typename _Tp::result_type result_type; }; template struct __weak_result_type_imp<_Tp, false> : public __maybe_derive_from_unary_function<_Tp>, public __maybe_derive_from_binary_function<_Tp> { }; template struct __weak_result_type : public __weak_result_type_imp<_Tp> { }; // 0 argument case template struct __weak_result_type<_Rp ()> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (&)()> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (*)()> { typedef _Rp result_type; }; // 1 argument case template struct __weak_result_type<_Rp (_A1)> : public unary_function<_A1, _Rp> { }; template struct __weak_result_type<_Rp (&)(_A1)> : public unary_function<_A1, _Rp> { }; template struct __weak_result_type<_Rp (*)(_A1)> : public unary_function<_A1, _Rp> { }; template struct __weak_result_type<_Rp (_Cp::*)()> : public unary_function<_Cp*, _Rp> { }; template struct __weak_result_type<_Rp (_Cp::*)() const> : public unary_function { }; template struct __weak_result_type<_Rp (_Cp::*)() volatile> : public unary_function { }; template struct __weak_result_type<_Rp (_Cp::*)() const volatile> : public unary_function { }; // 2 argument case template struct __weak_result_type<_Rp (_A1, _A2)> : public binary_function<_A1, _A2, _Rp> { }; template struct __weak_result_type<_Rp (*)(_A1, _A2)> : public binary_function<_A1, _A2, _Rp> { }; template struct __weak_result_type<_Rp (&)(_A1, _A2)> : public binary_function<_A1, _A2, _Rp> { }; template struct __weak_result_type<_Rp (_Cp::*)(_A1)> : public binary_function<_Cp*, _A1, _Rp> { }; template struct __weak_result_type<_Rp (_Cp::*)(_A1) const> : public binary_function { }; template struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile> : public binary_function { }; template struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile> : public binary_function { }; #ifndef _LIBCPP_HAS_NO_VARIADICS // 3 or more arguments template struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile> { typedef _Rp result_type; }; template struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> { typedef _Rp result_type; }; #endif // _LIBCPP_HAS_NO_VARIADICS -// __invoke +#ifndef _LIBCPP_CXX03_LANG -#ifndef _LIBCPP_HAS_NO_VARIADICS - -// bullets 1 and 2 - -template -inline _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)) -{ - return (_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...); -} - -template -inline _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)) -{ - return ((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...); -} - -// bullets 3 and 4 - -template -inline _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0) - -> decltype(_VSTD::forward<_A0>(__a0).*__f) -{ - return _VSTD::forward<_A0>(__a0).*__f; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _A0&& __a0) - -> decltype((*_VSTD::forward<_A0>(__a0)).*__f) -{ - return (*_VSTD::forward<_A0>(__a0)).*__f; -} - -// bullet 5 - -template -inline _LIBCPP_INLINE_VISIBILITY -auto -__invoke(_Fp&& __f, _Args&& ...__args) - -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) -{ - return _VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...); -} template struct __invoke_return { typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_Args>()...)) type; }; -#else // _LIBCPP_HAS_NO_VARIADICS +#else // defined(_LIBCPP_CXX03_LANG) #include <__functional_base_03> -#endif // _LIBCPP_HAS_NO_VARIADICS +#endif // !defined(_LIBCPP_CXX03_LANG) template struct __invoke_void_return_wrapper { #ifndef _LIBCPP_HAS_NO_VARIADICS template static _Ret __call(_Args&&... __args) { return __invoke(_VSTD::forward<_Args>(__args)...); } #else template static _Ret __call(_Fn __f) { return __invoke(__f); } template static _Ret __call(_Fn __f, _A0& __a0) { return __invoke(__f, __a0); } template static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) { return __invoke(__f, __a0, __a1); } template static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){ return __invoke(__f, __a0, __a1, __a2); } #endif }; template <> struct __invoke_void_return_wrapper { #ifndef _LIBCPP_HAS_NO_VARIADICS template static void __call(_Args&&... __args) { __invoke(_VSTD::forward<_Args>(__args)...); } #else template static void __call(_Fn __f) { __invoke(__f); } template static void __call(_Fn __f, _A0& __a0) { __invoke(__f, __a0); } template static void __call(_Fn __f, _A0& __a0, _A1& __a1) { __invoke(__f, __a0, __a1); } template static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) { __invoke(__f, __a0, __a1, __a2); } #endif }; template class _LIBCPP_TYPE_VIS_ONLY reference_wrapper : public __weak_result_type<_Tp> { public: // types typedef _Tp type; private: type* __f_; public: // construct/copy/destroy _LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT : __f_(_VSTD::addressof(__f)) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES private: reference_wrapper(type&&); public: // = delete; // do not bind to temps #endif // access _LIBCPP_INLINE_VISIBILITY operator type& () const _NOEXCEPT {return *__f_;} _LIBCPP_INLINE_VISIBILITY type& get() const _NOEXCEPT {return *__f_;} #ifndef _LIBCPP_HAS_NO_VARIADICS // invoke template _LIBCPP_INLINE_VISIBILITY typename __invoke_of::type operator() (_ArgTypes&&... __args) const { return __invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); } #else _LIBCPP_INLINE_VISIBILITY typename __invoke_return::type operator() () const { return __invoke(get()); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return0::type operator() (_A0& __a0) const { return __invoke(get(), __a0); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return0::type operator() (_A0 const& __a0) const { return __invoke(get(), __a0); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return1::type operator() (_A0& __a0, _A1& __a1) const { return __invoke(get(), __a0, __a1); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return1::type operator() (_A0 const& __a0, _A1& __a1) const { return __invoke(get(), __a0, __a1); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return1::type operator() (_A0& __a0, _A1 const& __a1) const { return __invoke(get(), __a0, __a1); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return1::type operator() (_A0 const& __a0, _A1 const& __a1) const { return __invoke(get(), __a0, __a1); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { return __invoke(get(), __a0, __a1, __a2); } template _LIBCPP_INLINE_VISIBILITY typename __invoke_return2::type operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { return __invoke(get(), __a0, __a1, __a2); } #endif // _LIBCPP_HAS_NO_VARIADICS }; -template struct __is_reference_wrapper_impl : public false_type {}; -template struct __is_reference_wrapper_impl > : public true_type {}; -template struct __is_reference_wrapper - : public __is_reference_wrapper_impl::type> {}; template inline _LIBCPP_INLINE_VISIBILITY reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT { return reference_wrapper<_Tp>(__t); } template inline _LIBCPP_INLINE_VISIBILITY reference_wrapper<_Tp> ref(reference_wrapper<_Tp> __t) _NOEXCEPT { return ref(__t.get()); } template inline _LIBCPP_INLINE_VISIBILITY reference_wrapper cref(const _Tp& __t) _NOEXCEPT { return reference_wrapper(__t); } template inline _LIBCPP_INLINE_VISIBILITY reference_wrapper cref(reference_wrapper<_Tp> __t) _NOEXCEPT { return cref(__t.get()); } #ifndef _LIBCPP_HAS_NO_VARIADICS #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES #ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS template void ref(const _Tp&&) = delete; template void cref(const _Tp&&) = delete; #else // _LIBCPP_HAS_NO_DELETED_FUNCTIONS template void ref(const _Tp&&);// = delete; template void cref(const _Tp&&);// = delete; #endif // _LIBCPP_HAS_NO_DELETED_FUNCTIONS #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES #endif // _LIBCPP_HAS_NO_VARIADICS #if _LIBCPP_STD_VER > 11 template struct __is_transparent { private: struct __two {char __lx; char __lxx;}; template static __two __test(...); template static char __test(typename _Up::is_transparent* = 0); public: static const bool value = sizeof(__test<_Tp1>(0)) == 1; }; #endif // allocator_arg_t struct _LIBCPP_TYPE_VIS_ONLY allocator_arg_t { }; #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MEMORY) extern const allocator_arg_t allocator_arg; #else constexpr allocator_arg_t allocator_arg = allocator_arg_t(); #endif // uses_allocator template struct __has_allocator_type { private: struct __two {char __lx; char __lxx;}; template static __two __test(...); template static char __test(typename _Up::allocator_type* = 0); public: static const bool value = sizeof(__test<_Tp>(0)) == 1; }; template ::value> struct __uses_allocator : public integral_constant::value> { }; template struct __uses_allocator<_Tp, _Alloc, false> : public false_type { }; template struct _LIBCPP_TYPE_VIS_ONLY uses_allocator : public __uses_allocator<_Tp, _Alloc> { }; #ifndef _LIBCPP_HAS_NO_VARIADICS // allocator construction template struct __uses_alloc_ctor_imp { static const bool __ua = uses_allocator<_Tp, _Alloc>::value; static const bool __ic = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; static const int value = __ua ? 2 - __ic : 0; }; template struct __uses_alloc_ctor : integral_constant::value> {}; template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &, _Args &&... __args ) { new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); } template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) { new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); } template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) { new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); } template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args) { __user_alloc_construct_impl( __uses_alloc_ctor<_Tp, _Allocator>(), __storage, __a, _VSTD::forward<_Args>(__args)... ); } #endif // _LIBCPP_HAS_NO_VARIADICS _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_FUNCTIONAL_BASE Index: projects/clang390-import/contrib/libc++/include/__hash_table =================================================================== --- projects/clang390-import/contrib/libc++/include/__hash_table (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__hash_table (revision 305076) @@ -1,2421 +1,2642 @@ // -*- 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 #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 + +#ifndef _LIBCPP_CXX03_LANG +template +union __hash_value_type; +#else +template +struct __hash_value_type; +#endif + +#ifndef _LIBCPP_CXX03_LANG +template +struct __is_hash_value_type_imp : false_type {}; + +template +struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value>> : true_type {}; + +template +struct __is_hash_value_type : false_type {}; + +template +struct __is_hash_value_type<_One> : __is_hash_value_type_imp::type> {}; +#endif + _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 __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type > { - typedef _Tp value_type; + typedef _Tp __node_value_type; size_t __hash_; - value_type __value_; + __node_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; + return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : + (__h < __bc ? __h : __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_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; +template +struct __hash_key_value_types { + static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, ""); + typedef _Tp key_type; + typedef _Tp __node_value_type; + typedef _Tp __container_value_type; + static const bool __is_map = false; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(_Tp const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& __get_value(__node_value_type const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n); + } +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __container_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v); + } +#endif +}; + +template +struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { + typedef _Key key_type; + typedef _Tp mapped_type; + typedef __hash_value_type<_Key, _Tp> __node_value_type; + typedef pair __container_value_type; + typedef pair<_Key, _Tp> __nc_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(__container_value_type const& __v) { + return __v.first; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t.__cc; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n.__cc); + } +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __nc_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v.__nc); + } +#endif + +}; + +template , + bool = _KVTypes::__is_map> +struct __hash_map_pointer_types {}; + +template +struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { + typedef typename _KVTypes::__map_value_type _Mv; + typedef typename __rebind_pointer<_AllocPtr, _Mv>::type + __map_value_type_pointer; + typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type + __const_map_value_type_pointer; +}; + +template ::element_type> +struct __hash_node_types; + +template +struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > + : public __hash_key_value_types<_Tp>, __hash_map_pointer_types<_Tp, _VoidPtr> + +{ + typedef __hash_key_value_types<_Tp> __base; + +public: + typedef ptrdiff_t difference_type; + typedef size_t size_type; + + typedef typename __rebind_pointer<_NodePtr, void>::type __void_pointer; + + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef _NodePtr __node_pointer; + + typedef __hash_node_base<__node_pointer> __node_base_type; + typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type + __node_base_pointer; + + typedef _Tp __node_value_type; + typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type + __node_value_type_pointer; + typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type + __const_node_value_type_pointer; +private: + static_assert(!is_const<__node_type>::value, + "_NodePtr should never be a pointer to const"); + static_assert((is_same::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); + static_assert((is_same::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + + + +template +struct __hash_node_types_from_iterator; template +struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; + + +template +struct __make_hash_node_types { + typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp; + typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr; + typedef __hash_node_types<_NodePtr> type; +}; + +template class _LIBCPP_TYPE_VIS_ONLY __hash_iterator { - typedef _NodePtr __node_pointer; + typedef __hash_node_types<_NodePtr> _NodeTypes; + 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 __rebind_pointer<__node_pointer, value_type>::type pointer; + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer 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 +template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator { - typedef _ConstNodePtr __node_pointer; + static_assert(!is_const::element_type>::value, ""); + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; - __node_pointer __node_; + __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 __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; + typedef __hash_iterator<_NodePtr> __non_const_iterator; + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + _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; + typedef __hash_node_types<_NodePtr> _NodeTypes; + 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 typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; typedef value_type& reference; - typedef typename __rebind_pointer<__node_pointer, value_type>::type pointer; + typedef typename _NodeTypes::__node_value_type_pointer 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; + typedef __hash_node_types<_ConstNodePtr> _NodeTypes; + 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 __rebind_pointer<__node_pointer, __non_const_node>::type __non_const_node_pointer; - +public: 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 __rebind_pointer<__node_pointer, const value_type>::type - pointer; + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer 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: + typedef __hash_node_types _NodeTypes; 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_)); + __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__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; + typedef typename + __make_hash_node_types::type + _NodeTypes; public: + + typedef typename _NodeTypes::__node_value_type __node_value_type; + typedef typename _NodeTypes::__container_value_type __container_value_type; + typedef typename _NodeTypes::key_type key_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; +#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE typedef typename __alloc_traits::size_type size_type; - typedef typename __alloc_traits::difference_type difference_type; +#else + typedef typename _NodeTypes::size_type size_type; +#endif + typedef typename _NodeTypes::difference_type difference_type; public: // Create __node - typedef __hash_node __node; + + typedef typename _NodeTypes::__node_type __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 __rebind_pointer<__node_pointer, __first_node>::type - __node_base_pointer; + typedef typename _NodeTypes::__void_pointer __void_pointer; + typedef typename _NodeTypes::__node_pointer __node_pointer; + typedef typename _NodeTypes::__node_pointer __node_const_pointer; + typedef typename _NodeTypes::__node_base_type __first_node; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; private: + // check for sane allocator pointer rebinding semantics. Rebinding the + // allocator for a new pointer type should be exactly the same as rebinding + // the pointer using 'pointer_traits'. + static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type + __node_base_allocator; + typedef allocator_traits<__node_base_allocator> __node_base_traits; + static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); +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_; + __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 +#ifndef _LIBCPP_CXX03_LANG __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 +#endif // _LIBCPP_CXX03_LANG ~__hash_table(); __hash_table& operator=(const __hash_table& __u); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#ifndef _LIBCPP_CXX03_LANG _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) +#ifndef _LIBCPP_CXX03_LANG + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_key_args(_Key const& __k, _Args&&... __args); + template - pair __emplace_unique(_Args&&... __args); + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_impl(_Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, + pair + >::type __emplace_unique(_First&& __f, _Second&& __s) { + return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + 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) + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - template + template _LIBCPP_INLINE_VISIBILITY - pair __insert_unique_value(_ValueTp&& __x); -#else + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + template _LIBCPP_INLINE_VISIBILITY - pair __insert_unique_value(const value_type& __x); -#endif + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } - pair __insert_unique(const value_type& __x); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_multi(_Args&&... __args); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - pair __insert_unique(value_type&& __x); + + _LIBCPP_INLINE_VISIBILITY + pair + __insert_unique(__container_value_type&& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x)); + } + + template ::value + >::type> + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(_Pp&& __x) { + return __emplace_unique(_VSTD::forward<_Pp>(__x)); + } + template - pair __insert_unique(_Pp&& __x); -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(_Pp&& __x) { + return __emplace_multi(_VSTD::forward<_Pp>(__x)); + } -#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 + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, _Pp&& __x) { + return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x)); + } +#else // !defined(_LIBCPP_CXX03_LANG) + template + pair __emplace_unique_key_args(_Key const&, _Args& __args); + + iterator __insert_multi(const __container_value_type& __x); + iterator __insert_multi(const_iterator __p, const __container_value_type& __x); +#endif + + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(const __container_value_type& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); + } + 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 +#ifndef _LIBCPP_CXX03_LANG 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); + __node_holder __construct_node(_Args&& ...__args); + + template + __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); +#else // _LIBCPP_CXX03_LANG + __node_holder __construct_node(const __container_value_type& __v); + __node_holder __construct_node_hash(size_t __hash, const __container_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) {} +#ifndef _LIBCPP_CXX03_LANG 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 {} +#endif // _LIBCPP_CXX03_LANG 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 +#ifndef _LIBCPP_CXX03_LANG 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 +#endif // _LIBCPP_CXX03_LANG template __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() { + static_assert((is_copy_constructible::value), + "Predicate must be copy-constructible."); + static_assert((is_copy_constructible::value), + "Hasher must be copy-constructible."); __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::destroy(__na, _NodeTypes::__get_ptr(__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 +#ifndef _LIBCPP_CXX03_LANG 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_holder __h = __construct_node(_NodeTypes::__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 +#endif // _LIBCPP_CXX03_LANG template template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) { + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value), + "__assign_unique may only be called with the containers value type"); + 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) { + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value || + is_same<_ItValueType, __node_value_type>::value), + "__assign_multi may only be called with the containers value type" + " or the nodes value type"); 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); + __insert_multi(_NodeTypes::__get_value(*__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 +#ifndef _LIBCPP_CXX03_LANG template -template +template _LIBCPP_INLINE_VISIBILITY pair::iterator, bool> -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(_ValueTp&& __x) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) #else template +template _LIBCPP_INLINE_VISIBILITY pair::iterator, bool> -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(const value_type& __x) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args& __args) #endif { -#if defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) - typedef const value_type& _ValueTp; -#endif - size_t __hash = hash_function()(__x); + + size_t __hash = hash_function()(__k); 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)) + if (key_eq()(__nd->__value_, __k)) goto __done; } } } { - __node_holder __h = __construct_node(_VSTD::forward<_ValueTp>(__x), __hash); +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node_hash(__hash, __args); +#endif 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())); + __pn = static_cast<__node_pointer>(static_cast<__void_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 +#ifndef _LIBCPP_CXX03_LANG template template pair::iterator, bool> -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_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 +#else // _LIBCPP_CXX03_LANG 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) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const __container_value_type& __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) + const __container_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 +#endif // _LIBCPP_CXX03_LANG 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->__hash_ == __hash + || __constrain_hash(__nd->__hash_, __bc) == __chash); __nd = __nd->__next_) { - if (key_eq()(__nd->__value_, __k)) + if ((__nd->__hash_ == __hash) && 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; + (__hash == __nd->__hash_ || __constrain_hash(__nd->__hash_, __bc) == __chash); __nd = __nd->__next_) { - if (key_eq()(__nd->__value_, __k)) + if ((__nd->__hash_ == __hash) && 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 +#ifndef _LIBCPP_CXX03_LANG template template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args) { + static_assert(!__is_hash_value_type<_Args...>::value, + "Construct cannot be called with a hash value type"); __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)...); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__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 +template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v, - size_t __hash) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash( + size_t __hash, _First&& __f, _Rest&& ...__rest) { + static_assert(!__is_hash_value_type<_First, _Rest...>::value, + "Construct cannot be called with a hash value type"); __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)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), + _VSTD::forward<_First>(__f), + _VSTD::forward<_Rest>(__rest)...); __h.get_deleter().__value_constructed = true; __h->__hash_ = __hash; __h->__next_ = nullptr; return __h; } -#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#else // _LIBCPP_CXX03_LANG template typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const __container_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); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__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) +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, + const __container_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); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__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 } + +#endif // _LIBCPP_CXX03_LANG 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 Index: projects/clang390-import/contrib/libc++/include/__mutex_base =================================================================== --- projects/clang390-import/contrib/libc++/include/__mutex_base (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__mutex_base (revision 305076) @@ -1,410 +1,438 @@ // -*- 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___MUTEX_BASE #define _LIBCPP___MUTEX_BASE #include <__config> #include #include -#ifndef _LIBCPP_HAS_NO_THREADS -#include -#endif +#include <__threading_support> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION +# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) +# else +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { - pthread_mutex_t __m_; +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; +#else + __libcpp_mutex_t __m_; +#endif public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR - constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} + constexpr mutex() _NOEXCEPT _LIBCPP_DEFAULT #else - mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} + mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;} #endif - ~mutex(); + ~mutex(); private: mutex(const mutex&);// = delete; mutex& operator=(const mutex&);// = delete; public: - void lock(); - bool try_lock() _NOEXCEPT; - void unlock() _NOEXCEPT; + void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); + bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); + void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); - typedef pthread_mutex_t* native_handle_type; + typedef __libcpp_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} }; struct _LIBCPP_TYPE_VIS defer_lock_t {}; struct _LIBCPP_TYPE_VIS try_to_lock_t {}; struct _LIBCPP_TYPE_VIS adopt_lock_t {}; #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) extern const defer_lock_t defer_lock; extern const try_to_lock_t try_to_lock; extern const adopt_lock_t adopt_lock; #else constexpr defer_lock_t defer_lock = defer_lock_t(); constexpr try_to_lock_t try_to_lock = try_to_lock_t(); constexpr adopt_lock_t adopt_lock = adopt_lock_t(); #endif + +// Forward declare lock_guard as a variadic template even in C++03 to keep +// the mangling consistent between dialects. +#if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) +template +class _LIBCPP_TYPE_VIS_ONLY lock_guard; +#endif + template -class _LIBCPP_TYPE_VIS_ONLY lock_guard +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) +#if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) +lock_guard +#else +lock_guard<_Mutex> +#endif { public: typedef _Mutex mutex_type; private: mutex_type& __m_; public: _LIBCPP_INLINE_VISIBILITY - explicit lock_guard(mutex_type& __m) + explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} _LIBCPP_INLINE_VISIBILITY - lock_guard(mutex_type& __m, adopt_lock_t) + lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_INLINE_VISIBILITY - ~lock_guard() {__m_.unlock();} + ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} private: - lock_guard(lock_guard const&);// = delete; - lock_guard& operator=(lock_guard const&);// = delete; + lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; + lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; }; template class _LIBCPP_TYPE_VIS_ONLY unique_lock { public: typedef _Mutex mutex_type; private: mutex_type* __m_; bool __owns_; public: _LIBCPP_INLINE_VISIBILITY unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY explicit unique_lock(mutex_type& __m) - : __m_(&__m), __owns_(true) {__m_->lock();} + : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(&__m), __owns_(false) {} + : __m_(_VSTD::addressof(__m)), __owns_(false) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, try_to_lock_t) - : __m_(&__m), __owns_(__m.try_lock()) {} + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, adopt_lock_t) - : __m_(&__m), __owns_(true) {} + : __m_(_VSTD::addressof(__m)), __owns_(true) {} template _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) - : __m_(&__m), __owns_(__m.try_lock_until(__t)) {} + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} template _LIBCPP_INLINE_VISIBILITY unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) - : __m_(&__m), __owns_(__m.try_lock_for(__d)) {} + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} _LIBCPP_INLINE_VISIBILITY ~unique_lock() { if (__owns_) __m_->unlock(); } private: unique_lock(unique_lock const&); // = delete; unique_lock& operator=(unique_lock const&); // = delete; public: #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) {__u.__m_ = nullptr; __u.__owns_ = false;} _LIBCPP_INLINE_VISIBILITY unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { if (__owns_) __m_->unlock(); __m_ = __u.__m_; __owns_ = __u.__owns_; __u.__m_ = nullptr; __u.__owns_ = false; return *this; } #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void lock(); bool try_lock(); template bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); template bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); void unlock(); _LIBCPP_INLINE_VISIBILITY void swap(unique_lock& __u) _NOEXCEPT { _VSTD::swap(__m_, __u.__m_); _VSTD::swap(__owns_, __u.__owns_); } _LIBCPP_INLINE_VISIBILITY mutex_type* release() _NOEXCEPT { mutex_type* __m = __m_; __m_ = nullptr; __owns_ = false; return __m; } _LIBCPP_INLINE_VISIBILITY bool owns_lock() const _NOEXCEPT {return __owns_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool () const _NOEXCEPT {return __owns_;} _LIBCPP_INLINE_VISIBILITY mutex_type* mutex() const _NOEXCEPT {return __m_;} }; template void unique_lock<_Mutex>::lock() { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); __m_->lock(); __owns_ = true; } template bool unique_lock<_Mutex>::try_lock() { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); __owns_ = __m_->try_lock(); return __owns_; } template template bool unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); __owns_ = __m_->try_lock_for(__d); return __owns_; } template template bool unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { if (__m_ == nullptr) __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); if (__owns_) __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); __owns_ = __m_->try_lock_until(__t); return __owns_; } template void unique_lock<_Mutex>::unlock() { if (!__owns_) __throw_system_error(EPERM, "unique_lock::unlock: not locked"); __m_->unlock(); __owns_ = false; } template inline _LIBCPP_INLINE_VISIBILITY void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT {__x.swap(__y);} //enum class cv_status _LIBCPP_DECLARE_STRONG_ENUM(cv_status) { no_timeout, timeout }; _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) class _LIBCPP_TYPE_VIS condition_variable { - pthread_cond_t __cv_; +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; +#else + __libcpp_condvar_t __cv_; +#endif + public: _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_HAS_NO_CONSTEXPR - constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} + constexpr condition_variable() _NOEXCEPT _LIBCPP_DEFAULT #else - condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} + condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;} #endif ~condition_variable(); private: condition_variable(const condition_variable&); // = delete; condition_variable& operator=(const condition_variable&); // = delete; public: void notify_one() _NOEXCEPT; void notify_all() _NOEXCEPT; void wait(unique_lock& __lk) _NOEXCEPT; template void wait(unique_lock& __lk, _Predicate __pred); template cv_status wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t); template bool wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred); template cv_status wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d); template bool _LIBCPP_INLINE_VISIBILITY wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); - typedef pthread_cond_t* native_handle_type; + typedef __libcpp_condvar_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} private: void __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; }; #endif // !_LIBCPP_HAS_NO_THREADS template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < chrono::__is_duration<_To>::value, _To >::type __ceil(chrono::duration<_Rep, _Period> __d) { using namespace chrono; _To __r = duration_cast<_To>(__d); if (__r < __d) ++__r; return __r; } #ifndef _LIBCPP_HAS_NO_THREADS template void condition_variable::wait(unique_lock& __lk, _Predicate __pred) { while (!__pred()) wait(__lk); } template cv_status condition_variable::wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; wait_for(__lk, __t - _Clock::now()); return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; } template bool condition_variable::wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { while (!__pred()) { if (wait_until(__lk, __t) == cv_status::timeout) return __pred(); } return true; } template cv_status condition_variable::wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d) { using namespace chrono; if (__d <= __d.zero()) return cv_status::timeout; typedef time_point > __sys_tpf; typedef time_point __sys_tpi; __sys_tpf _Max = __sys_tpi::max(); system_clock::time_point __s_now = system_clock::now(); steady_clock::time_point __c_now = steady_clock::now(); if (_Max - __d > __s_now) __do_timed_wait(__lk, __s_now + __ceil(__d)); else __do_timed_wait(__lk, __sys_tpi::max()); return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; } template inline bool condition_variable::wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) { return wait_until(__lk, chrono::steady_clock::now() + __d, _VSTD::move(__pred)); } #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MUTEX_BASE Index: projects/clang390-import/contrib/libc++/include/__threading_support =================================================================== --- projects/clang390-import/contrib/libc++/include/__threading_support (nonexistent) +++ projects/clang390-import/contrib/libc++/include/__threading_support (revision 305076) @@ -0,0 +1,205 @@ +// -*- 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_THREADING_SUPPORT +#define _LIBCPP_THREADING_SUPPORT + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#include +#include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) + +// Mutex +#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t __libcpp_mutex_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m) +{ + pthread_mutexattr_t attr; + int __ec = pthread_mutexattr_init(&attr); + if (__ec) return __ec; + __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (__ec) + { + pthread_mutexattr_destroy(&attr); + return __ec; + } + __ec = pthread_mutex_init(__m, &attr); + if (__ec) + { + pthread_mutexattr_destroy(&attr); + return __ec; + } + __ec = pthread_mutexattr_destroy(&attr); + if (__ec) + { + pthread_mutex_destroy(__m); + return __ec; + } + return 0; +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_lock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_lock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_trylock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_trylock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_unlock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) +{ + return pthread_mutex_destroy(__m); +} + +// Condition variable +#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER +typedef pthread_cond_t __libcpp_condvar_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) +{ + return pthread_cond_signal(__cv); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) +{ + return pthread_cond_broadcast(__cv); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) +{ + return pthread_cond_wait(__cv, __m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) +{ + return pthread_cond_timedwait(__cv, __m, __ts); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) +{ + return pthread_cond_destroy(__cv); +} + +// Thread id +typedef pthread_t __libcpp_thread_id; + +// Returns non-zero if the thread ids are equal, otherwise 0 +inline _LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) +{ + return pthread_equal(t1, t2) != 0; +} + +// Returns non-zero if t1 < t2, otherwise 0 +inline _LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) +{ + return t1 < t2; +} + +// Thread +typedef pthread_t __libcpp_thread_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) +{ + return pthread_create(__t, 0, __func, __arg); +} + +inline _LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return pthread_self(); +} + +inline _LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) +{ + return *__t; +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_join(__libcpp_thread_t* __t) +{ + return pthread_join(*__t, 0); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_detach(__libcpp_thread_t* __t) +{ + return pthread_detach(*__t); +} + +inline _LIBCPP_ALWAYS_INLINE +void __libcpp_thread_yield() +{ + sched_yield(); +} + +// Thread local storage +typedef pthread_key_t __libcpp_tl_key; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*)) +{ + return pthread_key_create(__key, __at_exit); +} + +inline _LIBCPP_ALWAYS_INLINE +void* __libcpp_tl_get(__libcpp_tl_key __key) +{ + return pthread_getspecific(__key); +} + +inline _LIBCPP_ALWAYS_INLINE +void __libcpp_tl_set(__libcpp_tl_key __key, void* __p) +{ + pthread_setspecific(__key, __p); +} + +#else // !_LIBCPP_HAS_THREAD_API_PTHREAD + #error "No thread API selected." +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP_THREADING_SUPPORT Index: projects/clang390-import/contrib/libc++/include/__tree =================================================================== --- projects/clang390-import/contrib/libc++/include/__tree (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__tree (revision 305076) @@ -1,2292 +1,2647 @@ // -*- 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; +template class __tree_end_node; +template class __tree_node_base; +template class __tree_node; + +#ifndef _LIBCPP_CXX03_LANG +template +union __value_type; +#else +template +struct __value_type; +#endif + +template class __map_node_destructor; +template class _LIBCPP_TYPE_VIS_ONLY __map_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __map_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_; + __x = __x->__parent_unsafe(); + return __x->__parent_unsafe(); } +template +inline _LIBCPP_INLINE_VISIBILITY +_EndNodePtr +__tree_next_iter(_NodePtr __x) _NOEXCEPT +{ + if (__x->__right_ != nullptr) + return static_cast<_EndNodePtr>(__tree_min(__x->__right_)); + while (!__tree_is_left_child(__x)) + __x = __x->__parent_unsafe(); + return static_cast<_EndNodePtr>(__x->__parent_); +} + // Returns: pointer to the previous in-order node before __x. // Precondition: __x != nullptr. -template +// Note: __x may be the end node. +template +inline _LIBCPP_INLINE_VISIBILITY _NodePtr -__tree_prev(_NodePtr __x) _NOEXCEPT +__tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { if (__x->__left_ != nullptr) return __tree_max(__x->__left_); - while (__tree_is_left_child(__x)) - __x = __x->__parent_; - return __x->__parent_; + _NodePtr __xx = static_cast<_NodePtr>(__x); + while (__tree_is_left_child(__xx)) + __xx = __xx->__parent_unsafe(); + return __xx->__parent_unsafe(); } // 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; + __x->__right_->__set_parent(__x); __y->__parent_ = __x->__parent_; if (__tree_is_left_child(__x)) __x->__parent_->__left_ = __y; else - __x->__parent_->__right_ = __y; + __x->__parent_unsafe()->__right_ = __y; __y->__left_ = __x; - __x->__parent_ = __y; + __x->__set_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; + __x->__left_->__set_parent(__x); __y->__parent_ = __x->__parent_; if (__tree_is_left_child(__x)) __x->__parent_->__left_ = __y; else - __x->__parent_->__right_ = __y; + __x->__parent_unsafe()->__right_ = __y; __y->__right_ = __x; - __x->__parent_ = __y; + __x->__set_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_) + while (__x != __root && !__x->__parent_unsafe()->__is_black_) { // __x->__parent_ != __root because __x->__parent_->__is_black == false - if (__tree_is_left_child(__x->__parent_)) + if (__tree_is_left_child(__x->__parent_unsafe())) { - _NodePtr __y = __x->__parent_->__parent_->__right_; + _NodePtr __y = __x->__parent_unsafe()->__parent_unsafe()->__right_; if (__y != nullptr && !__y->__is_black_) { - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = true; - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = __x == __root; __y->__is_black_ = true; } else { if (!__tree_is_left_child(__x)) { - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __tree_left_rotate(__x); } - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = true; - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = false; __tree_right_rotate(__x); break; } } else { - _NodePtr __y = __x->__parent_->__parent_->__left_; + _NodePtr __y = __x->__parent_unsafe()->__parent_->__left_; if (__y != nullptr && !__y->__is_black_) { - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = true; - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = __x == __root; __y->__is_black_ = true; } else { if (__tree_is_left_child(__x)) { - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __tree_right_rotate(__x); } - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __x->__is_black_ = true; - __x = __x->__parent_; + __x = __x->__parent_unsafe(); __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_; + __w = __y->__parent_unsafe()->__right_; else __root = __x; // __w == nullptr } else { - __y->__parent_->__right_ = __x; + __y->__parent_unsafe()->__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->__parent_unsafe()->__right_ = __y; __y->__left_ = __z->__left_; - __y->__left_->__parent_ = __y; + __y->__left_->__set_parent(__y); __y->__right_ = __z->__right_; if (__y->__right_ != nullptr) - __y->__right_->__parent_ = __y; + __y->__right_->__set_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_); + __w->__parent_unsafe()->__is_black_ = false; + __tree_left_rotate(__w->__parent_unsafe()); // __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 = __w->__parent_unsafe(); // __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_unsafe()->__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 = __w->__parent_unsafe(); } // __w has a right red child, left child may be null - __w->__is_black_ = __w->__parent_->__is_black_; - __w->__parent_->__is_black_ = true; + __w->__is_black_ = __w->__parent_unsafe()->__is_black_; + __w->__parent_unsafe()->__is_black_ = true; __w->__right_->__is_black_ = true; - __tree_left_rotate(__w->__parent_); + __tree_left_rotate(__w->__parent_unsafe()); break; } } else { if (!__w->__is_black_) { __w->__is_black_ = true; - __w->__parent_->__is_black_ = false; - __tree_right_rotate(__w->__parent_); + __w->__parent_unsafe()->__is_black_ = false; + __tree_right_rotate(__w->__parent_unsafe()); // __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 = __w->__parent_unsafe(); // __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_unsafe()->__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 = __w->__parent_unsafe(); } // __w has a left red child, right child may be null - __w->__is_black_ = __w->__parent_->__is_black_; - __w->__parent_->__is_black_ = true; + __w->__is_black_ = __w->__parent_unsafe()->__is_black_; + __w->__parent_unsafe()->__is_black_ = true; __w->__left_->__is_black_ = true; - __tree_right_rotate(__w->__parent_); + __tree_right_rotate(__w->__parent_unsafe()); break; } } } } } } -template class __map_node_destructor; +// node traits -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; + +#ifndef _LIBCPP_CXX03_LANG +template +struct __is_tree_value_type_imp : false_type {}; + +template +struct __is_tree_value_type_imp<__value_type<_Key, _Value>> : true_type {}; + +template +struct __is_tree_value_type : false_type {}; + +template +struct __is_tree_value_type<_One> : __is_tree_value_type_imp::type> {}; +#endif + +template +struct __tree_key_value_types { + typedef _Tp key_type; + typedef _Tp __node_value_type; + typedef _Tp __container_value_type; + static const bool __is_map = false; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(_Tp const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& __get_value(__node_value_type const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n); + } + +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __container_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v); + } +#endif +}; + +template +struct __tree_key_value_types<__value_type<_Key, _Tp> > { + typedef _Key key_type; + typedef _Tp mapped_type; + typedef __value_type<_Key, _Tp> __node_value_type; + typedef pair __container_value_type; + typedef pair<_Key, _Tp> __nc_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& + __get_key(__node_value_type const& __t) { + return __t.__cc.first; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + key_type const&>::type + __get_key(_Up& __t) { + return __t.first; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& + __get_value(__node_value_type const& __t) { + return __t.__cc; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n.__cc); + } + +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __nc_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v.__nc); + } +#endif +}; + +template +struct __tree_node_base_types { + typedef _VoidPtr __void_pointer; + + typedef __tree_node_base<__void_pointer> __node_base_type; + typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type + __node_base_pointer; + + typedef __tree_end_node<__node_base_pointer> __end_node_type; + typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type + __end_node_pointer; +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB) + typedef __end_node_pointer __parent_pointer; +#else + typedef typename conditional< + is_pointer<__end_node_pointer>::value, + __end_node_pointer, + __node_base_pointer>::type __parent_pointer; +#endif + private: + static_assert((is_same::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); +}; - allocator_type& __na_; +template , + bool = _KVTypes::__is_map> +struct __tree_map_pointer_types {}; - __tree_node_destructor& operator=(const __tree_node_destructor&); +template +struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { + typedef typename _KVTypes::__map_value_type _Mv; + typedef typename __rebind_pointer<_AllocPtr, _Mv>::type + __map_value_type_pointer; + typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type + __const_map_value_type_pointer; +}; +template ::element_type> +struct __tree_node_types; + +template +struct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> > + : public __tree_node_base_types<_VoidPtr>, + __tree_key_value_types<_Tp>, + __tree_map_pointer_types<_Tp, _VoidPtr> +{ + typedef __tree_node_base_types<_VoidPtr> __base; + typedef __tree_key_value_types<_Tp> __key_base; + typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base; public: - bool __value_constructed; - _LIBCPP_INLINE_VISIBILITY - explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT - : __na_(__na), - __value_constructed(__val) - {} + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef _NodePtr __node_pointer; - _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); - } + typedef _Tp __node_value_type; + typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type + __node_value_type_pointer; + typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type + __const_node_value_type_pointer; +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB) + typedef typename __base::__end_node_pointer __iter_pointer; +#else + typedef typename conditional< + is_pointer<__node_pointer>::value, + typename __base::__end_node_pointer, + __node_pointer>::type __iter_pointer; +#endif +private: + static_assert(!is_const<__node_type>::value, + "_NodePtr should never be a pointer to const"); + static_assert((is_same::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; - template friend class __map_node_destructor; +template +struct __make_tree_node_types { + typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type + _NodePtr; + typedef __tree_node_types<_NodePtr> type; }; // 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 __rebind_pointer<_VoidPtr, __tree_node_base<_VoidPtr> >::type - > + : public __tree_node_base_types<_VoidPtr>::__end_node_type { - __tree_node_base(const __tree_node_base&); - __tree_node_base& operator=(const __tree_node_base&); + typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes; + public: - typedef typename __rebind_pointer<_VoidPtr, __tree_node_base>::type pointer; - typedef typename __rebind_pointer<_VoidPtr, const __tree_node_base>::type const_pointer; + typedef typename _NodeBaseTypes::__node_base_pointer pointer; + typedef typename _NodeBaseTypes::__parent_pointer __parent_pointer; - typedef __tree_end_node base; - - pointer __right_; - pointer __parent_; + pointer __right_; + __parent_pointer __parent_; bool __is_black_; _LIBCPP_INLINE_VISIBILITY - __tree_node_base() _NOEXCEPT - : __right_(), __parent_(), __is_black_(false) {} + pointer __parent_unsafe() const { return static_cast(__parent_);} + + _LIBCPP_INLINE_VISIBILITY + void __set_parent(pointer __p) { + __parent_ = static_cast<__parent_pointer>(__p); + } + +private: + ~__tree_node_base() _LIBCPP_EQUAL_DELETE; + __tree_node_base(__tree_node_base const&) _LIBCPP_EQUAL_DELETE; + __tree_node_base& operator=(__tree_node_base const&) _LIBCPP_EQUAL_DELETE; }; template class __tree_node : public __tree_node_base<_VoidPtr> { public: - typedef __tree_node_base<_VoidPtr> base; - typedef _Tp value_type; + typedef _Tp __node_value_type; - value_type __value_; + __node_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) +private: + ~__tree_node() _LIBCPP_EQUAL_DELETE; + __tree_node(__tree_node const&) _LIBCPP_EQUAL_DELETE; + __tree_node& operator=(__tree_node const&) _LIBCPP_EQUAL_DELETE; +}; + + +template +class __tree_node_destructor +{ + typedef _Allocator allocator_type; + typedef allocator_traits __alloc_traits; + +public: + typedef typename __alloc_traits::pointer pointer; +private: + typedef __tree_node_types _NodeTypes; + allocator_type& __na_; + + __tree_node_destructor& operator=(const __tree_node_destructor&); + +public: + bool __value_constructed; + _LIBCPP_INLINE_VISIBILITY - explicit __tree_node(const value_type& __v) - : __value_(__v) {} -#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) + 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_, _NodeTypes::__get_ptr(__p->__value_)); + if (__p) + __alloc_traits::deallocate(__na_, __p, 1); + } + + template friend class __map_node_destructor; }; -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; + typedef __tree_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + typedef typename _NodeTypes::__end_node_pointer __end_node_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + typedef pointer_traits<__node_pointer> __pointer_traits; - __node_pointer __ptr_; + __iter_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 __rebind_pointer<__node_pointer, value_type>::type pointer; + typedef bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _DiffType difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer 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 reference operator*() const + {return __get_np()->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const - {return pointer_traits::pointer_to(__ptr_->__value_);} + {return pointer_traits::pointer_to(__get_np()->__value_);} _LIBCPP_INLINE_VISIBILITY __tree_iterator& operator++() { - __ptr_ = static_cast<__node_pointer>( - __tree_next(static_cast(__ptr_))); + __ptr_ = static_cast<__iter_pointer>( + __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__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_))); + __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>( + static_cast<__end_node_pointer>(__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) {} + _LIBCPP_INLINE_VISIBILITY + explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } 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 +template class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator { - typedef _ConstNodePtr __node_pointer; - typedef typename pointer_traits<__node_pointer>::element_type __node; + typedef __tree_node_types<_NodePtr> _NodeTypes; + typedef typename _NodeTypes::__node_pointer __node_pointer; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + typedef typename _NodeTypes::__end_node_pointer __end_node_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + typedef pointer_traits<__node_pointer> __pointer_traits; - __node_pointer __ptr_; + __iter_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 __rebind_pointer<__node_pointer, const value_type>::type pointer; + typedef bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _DiffType difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer 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 __rebind_pointer<__node_pointer, __non_const_node>::type - __non_const_node_pointer; - typedef __tree_iterator - __non_const_iterator; + 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 reference operator*() const + {return __get_np()->__value_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const - {return pointer_traits::pointer_to(__ptr_->__value_);} + {return pointer_traits::pointer_to(__get_np()->__value_);} _LIBCPP_INLINE_VISIBILITY __tree_const_iterator& operator++() { - 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_))); + __ptr_ = static_cast<__iter_pointer>( + __tree_next_iter<__end_node_pointer>(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 __rebind_pointer<__node_pointer, typename __node::base>::type - __node_base_pointer; - __ptr_ = static_cast<__node_pointer>( - __tree_prev(static_cast<__node_base_pointer>(__ptr_))); + __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>( + static_cast<__end_node_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) {} + _LIBCPP_INLINE_VISIBILITY + explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + 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; + +private: typedef allocator_traits __alloc_traits; + typedef typename __make_tree_node_types::type + _NodeTypes; + typedef typename _NodeTypes::key_type key_type; +public: + typedef typename _NodeTypes::__node_value_type __node_value_type; + typedef typename _NodeTypes::__container_value_type __container_value_type; + 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; +public: + typedef typename _NodeTypes::__void_pointer __void_pointer; - typedef __tree_node __node; - typedef __tree_node_base<__void_pointer> __node_base; + typedef typename _NodeTypes::__node_type __node; + typedef typename _NodeTypes::__node_pointer __node_pointer; + + typedef typename _NodeTypes::__node_base_type __node_base; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + + typedef typename _NodeTypes::__end_node_type __end_node_t; + typedef typename _NodeTypes::__end_node_pointer __end_node_ptr; + + typedef typename _NodeTypes::__parent_pointer __parent_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + 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; + typedef allocator_traits<__node_allocator> __node_traits; + private: - typedef typename __node_base::base __end_node_t; - typedef typename __rebind_pointer<__node_pointer, __end_node_t>::type - __end_node_ptr; - typedef __end_node_ptr __end_node_const_ptr; + // check for sane allocator pointer rebinding semantics. Rebinding the + // allocator for a new pointer type should be exactly the same as rebinding + // the pointer using 'pointer_traits'. + static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type + __node_base_allocator; + typedef allocator_traits<__node_base_allocator> __node_base_traits; + static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); - __node_pointer __begin_node_; +private: + __iter_pointer __begin_node_; __compressed_pair<__end_node_t, __node_allocator> __pair1_; __compressed_pair __pair3_; public: _LIBCPP_INLINE_VISIBILITY - __node_pointer __end_node() _NOEXCEPT + __iter_pointer __end_node() _NOEXCEPT { - return static_cast<__node_pointer> - ( - pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()) - ); + return static_cast<__iter_pointer>( + pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()) + ); } _LIBCPP_INLINE_VISIBILITY - __node_const_pointer __end_node() const _NOEXCEPT + __iter_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())) - ); + return static_cast<__iter_pointer>( + pointer_traits<__end_node_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_;} + __iter_pointer& __begin_node() _NOEXCEPT {return __begin_node_;} _LIBCPP_INLINE_VISIBILITY - const __node_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;} + const __iter_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_);} + __node_pointer __root() const _NOEXCEPT + {return static_cast<__node_pointer>(__end_node()->__left_);} + __node_base_pointer* __root_ptr() const _NOEXCEPT { + return _VSTD::addressof(__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 + +#ifndef _LIBCPP_CXX03_LANG + template + pair + __emplace_unique_key_args(_Key const&, _Args&&... __args); + template + iterator + __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...); + template - pair - __emplace_unique(_Args&&... __args); + pair __emplace_unique_impl(_Args&&... __args); + template - iterator - __emplace_multi(_Args&&... __args); + iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); template - iterator - __emplace_hint_unique(const_iterator __p, _Args&&... __args); + iterator __emplace_multi(_Args&&... __args); + template + iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, + pair + >::type __emplace_unique(_First&& __f, _Second&& __s) { + return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique(const_iterator __p, _Pp&& __x) { + return __emplace_hint_unique_extract_key(__p, _VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, iterator - __emplace_hint_multi(const_iterator __p, _Args&&... __args); -#endif // _LIBCPP_HAS_NO_VARIADICS + >::type __emplace_hint_unique(const_iterator __p, _First&& __f, _Second&& __s) { + return __emplace_hint_unique_key_args(__p, __f, + _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } - 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 + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args) { + return __emplace_hint_unique_impl(__p, _VSTD::forward<_Args>(__args)...); + } - 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); + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_fail_tag) { + return __emplace_hint_unique_impl(__p, _VSTD::forward<_Pp>(__x)); + } -#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); + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_self_tag) { + return __emplace_hint_unique_key_args(__p, __x, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_first_tag) { + return __emplace_hint_unique_key_args(__p, __x.first, _VSTD::forward<_Pp>(__x)); + } + +#else + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_key_args(_Key const&, _Args& __args); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&); #endif + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(const __container_value_type& __v) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__v), __v); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, const __container_value_type& __v) { + return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v); + } + +#ifdef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const __container_value_type& __v); + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, const __container_value_type& __v); +#else + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(__container_value_type&& __v) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__v), _VSTD::move(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, __container_value_type&& __v) { + return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), _VSTD::move(__v)); + } + + template ::type, + __container_value_type + >::value + >::type> + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(_Vp&& __v) { + return __emplace_unique(_VSTD::forward<_Vp>(__v)); + } + + template ::type, + __container_value_type + >::value + >::type> + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, _Vp&& __v) { + return __emplace_hint_unique(__p, _VSTD::forward<_Vp>(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(__container_value_type&& __v) { + return __emplace_multi(_VSTD::move(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, __container_value_type&& __v) { + return __emplace_hint_multi(__p, _VSTD::move(__v)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(_Vp&& __v) { + return __emplace_multi(_VSTD::forward<_Vp>(__v)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, _Vp&& __v) { + return __emplace_hint_multi(__p, _VSTD::forward<_Vp>(__v)); + } + +#endif // !_LIBCPP_CXX03_LANG + 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, + void __insert_node_at(__parent_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); + __iter_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; + __node_pointer __root, + __iter_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); + __iter_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; + __node_pointer __root, + __iter_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& + __node_base_pointer& + __find_leaf_low(__parent_pointer& __parent, const key_type& __v); + __node_base_pointer& + __find_leaf_high(__parent_pointer& __parent, const key_type& __v); + __node_base_pointer& __find_leaf(const_iterator __hint, - typename __node_base::pointer& __parent, const value_type& __v); + __parent_pointer& __parent, const key_type& __v); template - typename __node_base::pointer& - __find_equal(typename __node_base::pointer& __parent, const _Key& __v); + __node_base_pointer& + __find_equal(__parent_pointer& __parent, const _Key& __v); template - typename __node_base::pointer& - __find_equal(const_iterator __hint, typename __node_base::pointer& __parent, + __node_base_pointer& + __find_equal(const_iterator __hint, __parent_pointer& __parent, + __node_base_pointer& __dummy, const _Key& __v); -#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) +#ifndef _LIBCPP_CXX03_LANG 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); + __node_holder __construct_node(_Args&& ...__args); +#else + __node_holder __construct_node(const __container_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();} + { + if (__node_alloc() != __t.__node_alloc()) + clear(); + __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()), + : __begin_node_(__iter_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()), + : __begin_node_(__iter_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(); + __node_pointer __cache = static_cast<__node_pointer>(__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->__parent_unsafe()->__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) { + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value), + "__assign_unique may only be called with the containers value type"); + 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) { + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value || + is_same<_ItValueType, __node_value_type>::value), + "__assign_multi may only be called with the containers value type" + " or the nodes value type"); 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); + __insert_multi(_NodeTypes::__get_value(*__first)); } template __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) - : __begin_node_(__node_pointer()), + : __begin_node_(__iter_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()); + __end_node()->__left_->__parent_ = static_cast<__parent_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()); + __end_node()->__left_->__parent_ = static_cast<__parent_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()); + __end_node()->__left_->__parent_ = static_cast<__parent_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_)); + __insert_multi(__e, _NodeTypes::__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() { + static_assert((is_copy_constructible::value), + "Comparator must be copy-constructible."); 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::destroy(__na, _NodeTypes::__get_ptr(__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()); + __end_node()->__left_->__parent_ = static_cast<__parent_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()); + __t.__end_node()->__left_->__parent_ = static_cast<__parent_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) +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__parent_pointer& __parent, + const key_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_; + __parent = static_cast<__parent_pointer>(__nd); + return __nd->__right_; } } else { if (__nd->__left_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__left_); else { - __parent = static_cast<__node_base_pointer>(__nd); + __parent = static_cast<__parent_pointer>(__nd); return __parent->__left_; } } } } - __parent = static_cast<__node_base_pointer>(__end_node()); + __parent = static_cast<__parent_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) +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__parent_pointer& __parent, + const key_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); + __parent = static_cast<__parent_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<__parent_pointer>(__nd); + return __nd->__right_; } } } } - __parent = static_cast<__node_base_pointer>(__end_node()); + __parent = static_cast<__parent_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& +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) + __parent_pointer& __parent, + const key_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_); + __parent = static_cast<__parent_pointer>(__hint.__ptr_); return __parent->__left_; } else { - __parent = static_cast<__node_base_pointer>(__prior.__ptr_); - return __parent->__right_; + __parent = static_cast<__parent_pointer>(__prior.__ptr_); + return static_cast<__node_base_pointer>(__prior.__ptr_)->__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, +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_equal(__parent_pointer& __parent, const _Key& __v) { __node_pointer __nd = __root(); + __node_base_pointer* __nd_ptr = __root_ptr(); if (__nd != nullptr) { while (true) { if (value_comp()(__v, __nd->__value_)) { - if (__nd->__left_ != nullptr) + if (__nd->__left_ != nullptr) { + __nd_ptr = _VSTD::addressof(__nd->__left_); __nd = static_cast<__node_pointer>(__nd->__left_); - else - { - __parent = static_cast<__node_base_pointer>(__nd); + } else { + __parent = static_cast<__parent_pointer>(__nd); return __parent->__left_; } } else if (value_comp()(__nd->__value_, __v)) { - if (__nd->__right_ != nullptr) + if (__nd->__right_ != nullptr) { + __nd_ptr = _VSTD::addressof(__nd->__right_); __nd = static_cast<__node_pointer>(__nd->__right_); - else - { - __parent = static_cast<__node_base_pointer>(__nd); - return __parent->__right_; + } else { + __parent = static_cast<__parent_pointer>(__nd); + return __nd->__right_; } } else { - __parent = static_cast<__node_base_pointer>(__nd); - return __parent; + __parent = static_cast<__parent_pointer>(__nd); + return *__nd_ptr; } } } - __parent = static_cast<__node_base_pointer>(__end_node()); + __parent = static_cast<__parent_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& +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, - typename __node_base::pointer& __parent, + __parent_pointer& __parent, + __node_base_pointer& __dummy, 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_); + __parent = static_cast<__parent_pointer>(__hint.__ptr_); return __parent->__left_; } else { - __parent = static_cast<__node_base_pointer>(__prior.__ptr_); - return __parent->__right_; + __parent = static_cast<__parent_pointer>(__prior.__ptr_); + return static_cast<__node_base_pointer>(__prior.__ptr_)->__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) + if (__hint.__get_np()->__right_ == nullptr) { - __parent = static_cast<__node_base_pointer>(__hint.__ptr_); - return __parent->__right_; + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + return static_cast<__node_base_pointer>(__hint.__ptr_)->__right_; } else { - __parent = static_cast<__node_base_pointer>(__next.__ptr_); + __parent = static_cast<__parent_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; + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + __dummy = static_cast<__node_base_pointer>(__hint.__ptr_); + return __dummy; } template void -__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__node_base_pointer __parent, +__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__parent_pointer __parent, __node_base_pointer& __child, - __node_base_pointer __new_node) + __node_base_pointer __new_node) { __new_node->__left_ = nullptr; __new_node->__right_ = nullptr; __new_node->__parent_ = __parent; + // __new_node->__is_black_ is initialized in __tree_balance_after_insert __child = __new_node; if (__begin_node()->__left_ != nullptr) - __begin_node() = static_cast<__node_pointer>(__begin_node()->__left_); + __begin_node() = static_cast<__iter_pointer>(__begin_node()->__left_); __tree_balance_after_insert(__end_node()->__left_, __child); ++size(); } -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -#ifndef _LIBCPP_HAS_NO_VARIADICS +#ifndef _LIBCPP_CXX03_LANG +template +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) +#else +template +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args& __args) +#endif +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_equal(__parent, __k); + __node_pointer __r = static_cast<__node_pointer>(__child); + bool __inserted = false; + if (__child == nullptr) + { +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node(__args); +#endif + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + __inserted = true; + } + return pair(iterator(__r), __inserted); +} + +#ifndef _LIBCPP_CXX03_LANG template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( + const_iterator __p, _Key const& __k, _Args&&... __args) +#else +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( + const_iterator __p, _Key const& __k, _Args& __args) +#endif +{ + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k); + __node_pointer __r = static_cast<__node_pointer>(__child); + if (__child == nullptr) + { +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node(__args); +#endif + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + } + return iterator(__r); +} + + +#ifndef _LIBCPP_CXX03_LANG + +template template typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args) { + static_assert(!__is_tree_value_type<_Args...>::value, + "Cannot construct from __value_type"); __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)...); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__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) +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) { __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); - __node_base_pointer __parent; + __parent_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) +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(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_); + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __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_); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__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_); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__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; -} +#else // _LIBCPP_CXX03_LANG 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) +__tree<_Tp, _Compare, _Allocator>::__construct_node(const __container_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); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__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 +#endif // _LIBCPP_CXX03_LANG +#ifdef _LIBCPP_CXX03_LANG 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) +__tree<_Tp, _Compare, _Allocator>::__insert_multi(const __container_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); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__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) +__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const __container_value_type& __v) { - __node_base_pointer __parent; - __node_base_pointer& __child = __find_leaf(__p, __parent, __v); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__v)); __node_holder __h = __construct_node(__v); __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); return iterator(__h.release()); } +#endif template pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd) { - __node_base_pointer __parent; + __parent_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; + __parent_pointer __parent; + __node_base_pointer __dummy; __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_); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__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_); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__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); + __node_pointer __np = __p.__get_np(); + iterator __r(__p.__ptr_); ++__r; - if (__begin_node() == __np) + if (__begin_node() == __p.__ptr_) __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::destroy(__na, _NodeTypes::__get_ptr( + const_cast<__node_value_type&>(*__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(); + __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; - __rt = static_cast<__node_const_pointer>(__rt->__left_); + __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) - __rt = static_cast<__node_const_pointer>(__rt->__right_); + __rt = static_cast<__node_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(); + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; - __rt = static_cast<__node_const_pointer>(__rt->__left_); + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) - __rt = static_cast<__node_const_pointer>(__rt->__right_); + __rt = static_cast<__node_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) + __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_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) + __iter_pointer __result) { while (__root != nullptr) { if (!value_comp()(__root->__value_, __v)) { - __result = __root; + __result = static_cast<__iter_pointer>(__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 + __node_pointer __root, + __iter_pointer __result) const { while (__root != nullptr) { if (!value_comp()(__root->__value_, __v)) { - __result = __root; - __root = static_cast<__node_const_pointer>(__root->__left_); + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_const_pointer>(__root->__right_); + __root = static_cast<__node_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) + __iter_pointer __result) { while (__root != nullptr) { if (value_comp()(__v, __root->__value_)) { - __result = __root; + __result = static_cast<__iter_pointer>(__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 + __node_pointer __root, + __iter_pointer __result) const { while (__root != nullptr) { if (value_comp()(__v, __root->__value_)) { - __result = __root; - __root = static_cast<__node_const_pointer>(__root->__left_); + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_const_pointer>(__root->__right_); + __root = static_cast<__node_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(); + __iter_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; + __result = static_cast<__iter_pointer>(__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_)) + static_cast<__iter_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(); + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; - __rt = static_cast<__node_const_pointer>(__rt->__left_); + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) - __rt = static_cast<__node_const_pointer>(__rt->__right_); + __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(const_iterator(__rt), const_iterator( __rt->__right_ != nullptr ? - static_cast<__node_const_pointer>(__tree_min(__rt->__right_)) + static_cast<__iter_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(); + __iter_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; + __result = static_cast<__iter_pointer>(__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), + return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__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(); + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __result = __rt; - __rt = static_cast<__node_const_pointer>(__rt->__left_); + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) - __rt = static_cast<__node_const_pointer>(__rt->__right_); + __rt = static_cast<__node_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(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_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) + __node_pointer __np = __p.__get_np(); + if (__begin_node() == __p.__ptr_) { if (__np->__right_ != nullptr) - __begin_node() = static_cast<__node_pointer>(__np->__right_); + __begin_node() = static_cast<__iter_pointer>(__np->__right_); else - __begin_node() = static_cast<__node_pointer>(__np->__parent_); + __begin_node() = static_cast<__iter_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 Index: projects/clang390-import/contrib/libc++/include/__tuple =================================================================== --- projects/clang390-import/contrib/libc++/include/__tuple (revision 305075) +++ projects/clang390-import/contrib/libc++/include/__tuple (revision 305076) @@ -1,363 +1,438 @@ // -*- 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___TUPLE #define _LIBCPP___TUPLE #include <__config> #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_TYPE_VIS_ONLY tuple_size; template class _LIBCPP_TYPE_VIS_ONLY tuple_size : public tuple_size<_Tp> {}; template class _LIBCPP_TYPE_VIS_ONLY tuple_size : public tuple_size<_Tp> {}; template class _LIBCPP_TYPE_VIS_ONLY tuple_size : public tuple_size<_Tp> {}; template class _LIBCPP_TYPE_VIS_ONLY tuple_element; template class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const _Tp> { public: typedef typename add_const::type>::type type; }; template class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, volatile _Tp> { public: typedef typename add_volatile::type>::type type; }; template class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const volatile _Tp> { public: typedef typename add_cv::type>::type type; }; template struct __tuple_like : false_type {}; template struct __tuple_like : public __tuple_like<_Tp> {}; template struct __tuple_like : public __tuple_like<_Tp> {}; template struct __tuple_like : public __tuple_like<_Tp> {}; // tuple specializations #if !defined(_LIBCPP_HAS_NO_VARIADICS) + +template struct __tuple_indices {}; + +template +struct __integer_sequence { + template