diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-06-26 18:39:06 +0000 |
commit | 21543d4cd558cada630271a0cf3075ad7ce94cbf (patch) | |
tree | 08bdb3f3e0a9d0f71e72bb56d9ddb7b916e7dfeb /libstdc++-v3/include/bits | |
parent | ed0bc1ffb674fe93d0df68654b5bb76869f0bc8c (diff) | |
download | gcc-21543d4cd558cada630271a0cf3075ad7ce94cbf.tar.gz |
2013-06-26 Basile Starynkevitch <basile@starynkevitch.net>
{{merged with trunk [4.9] svn rev. 196654-200426}}
MELT branch merged with trunk rev. 200426 using svnmerge.py
[gcc/]
2013-06-26 Basile Starynkevitch <basile@starynkevitch.net>
{{merge with trunk [4.9] svn rev. 196654-200426}}
* melt-runtime.c (melt_val2passflag): TODO_ggc_collect &
TODO_do_not_ggc_collect are conditionalized.
* melt/generated/warmelt-first+03.cc: Manually remove calls to
MELT_TRACE_EXIT_LOCATION macro.
* melt/generated/warmelt-base+03.cc: Ditto.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@200430 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include/bits')
35 files changed, 2122 insertions, 364 deletions
diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index 33ea145d521..e68d3171095 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -412,7 +412,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, * Returns @c __a.max_size() if that expression is well-formed, * otherwise returns @c numeric_limits<size_type>::max() */ - static size_type max_size(const _Alloc& __a) + static size_type max_size(const _Alloc& __a) noexcept { return _S_max_size(__a); } /** diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 609fe8b0623..d9d755abba9 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -37,6 +37,10 @@ #include <stdint.h> #include <bits/atomic_lockfree_defines.h> +#ifndef _GLIBCXX_ALWAYS_INLINE +#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -94,11 +98,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION | (__m & __memory_order_modifier_mask)); } - inline void + _GLIBCXX_ALWAYS_INLINE void atomic_thread_fence(memory_order __m) noexcept { __atomic_thread_fence(__m); } - inline void + _GLIBCXX_ALWAYS_INLINE void atomic_signal_fence(memory_order __m) noexcept { __atomic_signal_fence(__m); } @@ -281,19 +285,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __atomic_flag_base{ _S_init(__i) } { } - bool + _GLIBCXX_ALWAYS_INLINE bool test_and_set(memory_order __m = memory_order_seq_cst) noexcept { return __atomic_test_and_set (&_M_i, __m); } - bool + _GLIBCXX_ALWAYS_INLINE bool test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_test_and_set (&_M_i, __m); } - void + _GLIBCXX_ALWAYS_INLINE void clear(memory_order __m = memory_order_seq_cst) noexcept { memory_order __b = __m & __memory_order_mask; @@ -304,7 +308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_clear (&_M_i, __m); } - void + _GLIBCXX_ALWAYS_INLINE void clear(memory_order __m = memory_order_seq_cst) volatile noexcept { memory_order __b = __m & __memory_order_mask; @@ -463,7 +467,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_lock_free() const volatile noexcept { return __atomic_is_lock_free(sizeof(_M_i), nullptr); } - void + _GLIBCXX_ALWAYS_INLINE void store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { memory_order __b = __m & __memory_order_mask; @@ -474,7 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_store_n(&_M_i, __i, __m); } - void + _GLIBCXX_ALWAYS_INLINE void store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { @@ -486,7 +490,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_store_n(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type load(memory_order __m = memory_order_seq_cst) const noexcept { memory_order __b = __m & __memory_order_mask; @@ -496,7 +500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_load_n(&_M_i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type load(memory_order __m = memory_order_seq_cst) const volatile noexcept { memory_order __b = __m & __memory_order_mask; @@ -506,7 +510,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_load_n(&_M_i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type exchange(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { @@ -514,14 +518,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type exchange(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_exchange_n(&_M_i, __i, __m); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_weak(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) noexcept { @@ -534,7 +538,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_weak(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) volatile noexcept @@ -548,7 +552,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_weak(__int_type& __i1, __int_type __i2, memory_order __m = memory_order_seq_cst) noexcept { @@ -556,7 +560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__m)); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_weak(__int_type& __i1, __int_type __i2, memory_order __m = memory_order_seq_cst) volatile noexcept { @@ -564,7 +568,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__m)); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) noexcept { @@ -577,7 +581,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) volatile noexcept @@ -592,7 +596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__int_type& __i1, __int_type __i2, memory_order __m = memory_order_seq_cst) noexcept { @@ -600,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__m)); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__int_type& __i1, __int_type __i2, memory_order __m = memory_order_seq_cst) volatile noexcept { @@ -608,52 +612,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__m)); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_add(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_add(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_sub(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_sub(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_and(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_and(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_or(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_or(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_xor(&_M_i, __i, __m); } - __int_type + _GLIBCXX_ALWAYS_INLINE __int_type fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_xor(&_M_i, __i, __m); } @@ -770,7 +774,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_lock_free() const volatile noexcept { return __atomic_is_lock_free(_M_type_size(1), nullptr); } - void + _GLIBCXX_ALWAYS_INLINE void store(__pointer_type __p, memory_order __m = memory_order_seq_cst) noexcept { @@ -783,7 +787,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_store_n(&_M_p, __p, __m); } - void + _GLIBCXX_ALWAYS_INLINE void store(__pointer_type __p, memory_order __m = memory_order_seq_cst) volatile noexcept { @@ -795,7 +799,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_store_n(&_M_p, __p, __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type load(memory_order __m = memory_order_seq_cst) const noexcept { memory_order __b = __m & __memory_order_mask; @@ -805,7 +809,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_load_n(&_M_p, __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type load(memory_order __m = memory_order_seq_cst) const volatile noexcept { memory_order __b = __m & __memory_order_mask; @@ -815,7 +819,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_load_n(&_M_p, __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type exchange(__pointer_type __p, memory_order __m = memory_order_seq_cst) noexcept { @@ -823,14 +827,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type exchange(__pointer_type __p, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_exchange_n(&_M_p, __p, __m); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, memory_order __m1, memory_order __m2) noexcept @@ -844,7 +848,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2); } - bool + _GLIBCXX_ALWAYS_INLINE bool compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, memory_order __m1, memory_order __m2) volatile noexcept @@ -859,22 +863,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) noexcept { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); } - __pointer_type + _GLIBCXX_ALWAYS_INLINE __pointer_type fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile noexcept { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); } diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index aa188f53a68..cbea5664e71 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -2767,10 +2767,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Stores characters from @a __is into @a __str until @a __delim is * found, the end of the stream is encountered, or str.max_size() - * is reached. If is.width() is non-zero, that is the limit on the - * number of characters stored into @a __str. Any previous - * contents of @a __str are erased. If @a __delim was encountered, - * it is extracted but not stored into @a __str. + * is reached. Any previous contents of @a __str are erased. If + * @a __delim is encountered, it is extracted but not stored into + * @a __str. */ template<typename _CharT, typename _Traits, typename _Alloc> basic_istream<_CharT, _Traits>& @@ -2785,10 +2784,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Stores characters from is into @a __str until '\n' is * found, the end of the stream is encountered, or str.max_size() - * is reached. If __is.width() is non-zero, that is the limit on - * the number of characters stored into @a __str. Any previous - * contents of @a __str are erased. If end of line was - * encountered, it is extracted but not stored into @a __str. + * is reached. Any previous contents of @a __str are erased. If + * end of line is encountered, it is extracted but not stored into + * @a __str. */ template<typename _CharT, typename _Traits, typename _Alloc> inline basic_istream<_CharT, _Traits>& @@ -3105,8 +3103,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; #endif +#if __cplusplus > 201103L + + inline namespace literals + { + inline namespace string_literals + { + + inline basic_string<char> + operator"" s(const char* __str, size_t __len) + { return basic_string<char>{__str, __len}; } + +#ifdef _GLIBCXX_USE_WCHAR_T + inline basic_string<wchar_t> + operator"" s(const wchar_t* __str, size_t __len) + { return basic_string<wchar_t>{__str, __len}; } +#endif + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + inline basic_string<char16_t> + operator"" s(const char16_t* __str, size_t __len) + { return basic_string<char16_t>{__str, __len}; } + + inline basic_string<char32_t> + operator"" s(const char32_t* __str, size_t __len) + { return basic_string<char32_t>{__str, __len}; } +#endif + + } // inline namespace string_literals + } // inline namespace literals + +#endif // __cplusplus > 201103L + _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/bits/c++14_warning.h b/libstdc++-v3/include/bits/c++14_warning.h new file mode 100644 index 00000000000..ff2adfa75da --- /dev/null +++ b/libstdc++-v3/include/bits/c++14_warning.h @@ -0,0 +1,37 @@ +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file bits/c++14_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _CXX14_WARNING_H +#define _CXX14_WARNING_H 1 + +#if __cplusplus <= 201103L +#error This file requires compiler and library support for the forthcoming \ +ISO C++ 2014 standard. This support is currently experimental, and must be \ +enabled with the -std=c++1y or -std=gnu++1y compiler options. +#endif + +#endif diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 04ae4cb7c3a..aca8484e222 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -84,6 +84,12 @@ # define _GLIBCXX_DEPRECATED #endif +// Macros for ABI tag attributes. +#ifndef _GLIBCXX_ABI_TAG_CXX11 +# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) +#endif + + #if __cplusplus // Macro for constexpr, to support in mixed 03/0x mode. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index c293495a2c2..0d0f7cc1e3c 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -248,7 +248,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_CONSTEXPR bool lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 < __c2; } + { + // LWG 467. + return (static_cast<unsigned char>(__c1) + < static_cast<unsigned char>(__c2)); + } static int compare(const char_type* __s1, const char_type* __s2, size_t __n) diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index 6c03c9869d0..02a18597be0 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -327,14 +327,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; // - // A fundamental type is `void' or and arithmetic type - // - template<typename _Tp> - struct __is_fundamental - : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> > - { }; - - // // A scalar type is an arithmetic type or a pointer type // template<typename _Tp> diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index 369e0eda531..8da73589869 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -191,7 +191,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: - erase(iterator __position) + _M_erase(iterator __position) { iterator __next = __position; ++__next; @@ -214,7 +214,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: - erase(iterator __first, iterator __last) + _M_erase(iterator __first, iterator __last) { if (__first == __last) return __first; @@ -381,7 +381,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __try { for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else push_back(*__first); +#endif } __catch(...) { diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index 608d678d8fc..c3cee971399 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -32,10 +32,14 @@ #pragma GCC system_header -#include <memory> -#if __cplusplus >= 201103L #include <initializer_list> -#endif +#include <bits/stl_iterator_base_types.h> +#include <bits/stl_iterator.h> +#include <bits/stl_algobase.h> +#include <bits/stl_function.h> +#include <bits/allocator.h> +#include <ext/alloc_traits.h> +#include <ext/aligned_buffer.h> namespace std _GLIBCXX_VISIBILITY(default) { @@ -96,20 +100,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Fwd_list_node() = default; - typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type - _M_storage; + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; _Tp* _M_valptr() noexcept - { - return static_cast<_Tp*>(static_cast<void*>(&_M_storage)); - } + { return _M_storage._M_ptr(); } const _Tp* _M_valptr() const noexcept - { - return static_cast<const _Tp*>(static_cast<const void*>(&_M_storage)); - } + { return _M_storage._M_ptr(); } }; /** @@ -339,7 +338,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Node* _M_get_node() - { return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); } + { + auto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); + return std::__addressof(*__ptr); + } template<typename... _Args> _Node* @@ -368,7 +370,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_put_node(_Node* __p) - { _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); } + { + typedef typename _Node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p); + _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1); + } _Fwd_list_node_base* _M_erase_after(_Fwd_list_node_base* __pos); @@ -421,8 +427,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Tp value_type; typedef typename _Alloc_traits::pointer pointer; typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; typedef _Fwd_list_iterator<_Tp> iterator; typedef _Fwd_list_const_iterator<_Tp> const_iterator; diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 246e9bb3bcf..8ce264ed72e 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -183,18 +183,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits> { + typedef std::allocator_traits<_Alloc> _Alloc_traits; + typedef typename _Alloc_traits::template rebind_alloc<_Value> + _Value_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Value_alloc_type> _Value_alloc_traits; + public: - typedef _Key key_type; - typedef _Value value_type; - typedef _Alloc allocator_type; - typedef _Equal key_equal; + typedef _Key key_type; + typedef _Value value_type; + typedef _Alloc allocator_type; + typedef _Equal key_equal; // mapped_type, if present, comes from _Map_base. // hasher, if present, comes from _Hash_code_base/_Hashtable_base. - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; + typedef typename _Value_alloc_traits::pointer pointer; + typedef typename _Value_alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; private: using __rehash_type = _RehashPolicy; @@ -236,8 +241,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _RehashPolicy, _Traits>; // Metaprogramming for picking apart hash caching. - using __hash_noexcept = __detail::__is_noexcept_hash<_Key, _H1>; - template<typename _Cond> using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>; @@ -246,12 +249,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Compile-time diagnostics. - // When hash codes are not cached the hash functor shall not - // throw because it is used in methods (erase, swap...) that - // shall not throw. - static_assert(__if_hash_not_cached<__hash_noexcept>::value, - "Cache the hash code" - " or qualify your hash functor with noexcept"); + // Getting a bucket index from a node shall not throw because it is used + // in methods (erase, swap...) that shall not throw. + static_assert(noexcept(declval<const _Hashtable&>() + ._M_bucket_index((const __node_type*)nullptr, + (std::size_t)0)), + "Cache the hash code or qualify your functors involved" + " in hash code and bucket index computation with noexcept"); // Following two static assertions are necessary to guarantee // that local_iterator will be default constructible. @@ -302,6 +306,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool _Constant_iteratorsa, bool _Unique_keysa> friend struct __detail::_Insert; + template<typename _Keya, typename _Valuea, typename _Alloca, + typename _ExtractKeya, typename _Equala, + typename _H1a, typename _H2a, typename _Hasha, + typename _RehashPolicya, typename _Traitsa, + bool _IsCopyAssignable> + friend struct __detail::_ReuseOrAllocNode; + + template<typename _Keya, typename _Valuea, typename _Alloca, + typename _ExtractKeya, typename _Equala, + typename _H1a, typename _H2a, typename _Hasha, + typename _RehashPolicya, typename _Traitsa, + bool _IsMoveAssignable> + friend struct __detail::_MoveReuseOrAllocNode; + using size_type = typename __hashtable_base::size_type; using difference_type = typename __hashtable_base::difference_type; @@ -313,12 +331,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const_local_iterator; private: - typedef typename _Alloc::template rebind<__node_type>::other - _Node_allocator_type; - typedef typename _Alloc::template rebind<__bucket_type>::other - _Bucket_allocator_type; + typedef typename _Alloc_traits::template rebind_alloc<__node_type> + _Node_alloc_type; + // Use __gnu_cxx to benefit from _S_always_equal and al. + typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; - using __before_begin = __detail::_Before_begin<_Node_allocator_type>; + typedef + typename _Alloc_traits::template rebind_alloc<__bucket_type> + _Bucket_alloc_type; + typedef std::allocator_traits<_Bucket_alloc_type> _Bucket_alloc_traits; + + using __before_begin = __detail::_Before_begin<_Node_alloc_type>; __bucket_type* _M_buckets; size_type _M_bucket_count; @@ -326,11 +349,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type _M_element_count; _RehashPolicy _M_rehash_policy; - _Node_allocator_type& + _Node_alloc_type& _M_node_allocator() { return _M_bbegin; } - const _Node_allocator_type& + const _Node_alloc_type& _M_node_allocator() const { return _M_bbegin; } @@ -359,6 +382,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_deallocate_buckets(__bucket_type*, size_type __n); + void + _M_deallocate_buckets() + { _M_deallocate_buckets(_M_buckets, _M_bucket_count); } + // Gets bucket begin, deals with the fact that non-empty buckets contain // their before begin node. __node_type* @@ -368,6 +395,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_begin() const { return static_cast<__node_type*>(_M_before_begin()._M_nxt); } + template<typename _UnaryOp> + void + _M_assign(const _Hashtable&, const _UnaryOp&); + + void + _M_move_assign(_Hashtable&&, std::true_type); + + void + _M_move_assign(_Hashtable&&, std::false_type); + + void + _M_reset() noexcept; + public: // Constructor, destructor, assignment, swap _Hashtable(size_type __bucket_hint, @@ -384,10 +424,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Hashtable(const _Hashtable&); - _Hashtable(_Hashtable&&); + _Hashtable(_Hashtable&&) noexcept; + + _Hashtable(const _Hashtable&, const allocator_type&); + + _Hashtable(_Hashtable&&, const allocator_type&); // Use delegating constructors. explicit + _Hashtable(const allocator_type& __a) + : _Hashtable(10, _H1(), __detail::_Mod_range_hashing(), + __detail::_Default_ranged_hash(), key_equal(), + __key_extract(), __a) + { } + + explicit _Hashtable(size_type __n = 10, const _H1& __hf = _H1(), const key_equal& __eql = key_equal(), @@ -420,34 +471,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { } _Hashtable& - operator=(const _Hashtable& __ht) - { - _Hashtable __tmp(__ht); - this->swap(__tmp); - return *this; - } + operator=(const _Hashtable& __ht); _Hashtable& operator=(_Hashtable&& __ht) + noexcept(_Node_alloc_traits::_S_nothrow_move()) { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__ht); + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__ht), + integral_constant<bool, __move_storage>()); return *this; } _Hashtable& operator=(initializer_list<value_type> __l) { - this->clear(); + clear(); this->insert(__l.begin(), __l.end()); return *this; } ~_Hashtable() noexcept; - void swap(_Hashtable&); + void + swap(_Hashtable&) + noexcept(_Node_alloc_traits::_S_nothrow_swap()); // Basic container operations iterator @@ -488,7 +538,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type max_size() const noexcept - { return _M_node_allocator().max_size(); } + { return _Node_alloc_traits::max_size(_M_node_allocator()); } // Observers key_equal @@ -585,7 +635,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: // Bucket index computation helpers. size_type - _M_bucket_index(__node_type* __n) const + _M_bucket_index(__node_type* __n) const noexcept { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); } size_type @@ -682,7 +732,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type erase(const key_type& __k) - { return _M_erase(__unique_keys(), __k); } + { + if (__builtin_expect(_M_bucket_count == 0, false)) + return 0; + return _M_erase(__unique_keys(), __k); + } iterator erase(const_iterator, const_iterator); @@ -721,15 +775,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_allocate_node(_Args&&... __args) { - __node_type* __n = _M_node_allocator().allocate(1); + auto __nptr = _Node_alloc_traits::allocate(_M_node_allocator(), 1); + __node_type* __n = std::__addressof(*__nptr); __try { - _M_node_allocator().construct(__n, std::forward<_Args>(__args)...); + _Value_alloc_type __a(_M_node_allocator()); + ::new ((void*)__n) __node_type(); + _Value_alloc_traits::construct(__a, __n->_M_valptr(), + std::forward<_Args>(__args)...); return __n; } __catch(...) { - _M_node_allocator().deallocate(__n, 1); + _Node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1); __throw_exception_again; } } @@ -743,8 +801,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_deallocate_node(__node_type* __n) { - _M_node_allocator().destroy(__n); - _M_node_allocator().deallocate(__n, 1); + typedef typename _Node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n); + _Value_alloc_type __a(_M_node_allocator()); + _Value_alloc_traits::destroy(__a, __n->_M_valptr()); + __n->~__node_type(); + _Node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1); } template<typename _Key, typename _Value, @@ -774,9 +836,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_allocate_buckets(size_type __n) { - _Bucket_allocator_type __alloc(_M_node_allocator()); + _Bucket_alloc_type __alloc(_M_node_allocator()); - __bucket_type* __p = __alloc.allocate(__n); + auto __ptr = _Bucket_alloc_traits::allocate(__alloc, __n); + __bucket_type* __p = std::__addressof(*__ptr); __builtin_memset(__p, 0, __n * sizeof(__bucket_type)); return __p; } @@ -788,10 +851,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_deallocate_buckets(__bucket_type* __p, size_type __n) + _M_deallocate_buckets(__bucket_type* __bkts, size_type __n) { - _Bucket_allocator_type __alloc(_M_node_allocator()); - __alloc.deallocate(__p, __n); + typedef typename _Bucket_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts); + _Bucket_alloc_type __alloc(_M_node_allocator()); + _Bucket_alloc_traits::deallocate(__alloc, __ptr, __n); } template<typename _Key, typename _Value, @@ -822,7 +887,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __hashtable_base(__exk, __h1, __h2, __h, __eq), __map_base(), __rehash_base(), - _M_bucket_count(0), _M_bbegin(__a), _M_element_count(0), _M_rehash_policy() @@ -846,7 +910,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __hashtable_base(__exk, __h1, __h2, __h, __eq), __map_base(), __rehash_base(), - _M_bucket_count(0), _M_bbegin(__a), _M_element_count(0), _M_rehash_policy() @@ -866,7 +929,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __catch(...) { clear(); - _M_deallocate_buckets(_M_buckets, _M_bucket_count); + _M_deallocate_buckets(); __throw_exception_again; } } @@ -876,49 +939,266 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, typename _Traits> _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>& + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=( + const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht) + { + if (&__ht == this) + return *this; + + if (_Node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_node_allocator(); + auto& __that_alloc = __ht._M_node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // Replacement allocator cannot free existing storage. + _M_deallocate_nodes(_M_begin()); + if (__builtin_expect(_M_bucket_count != 0, true)) + _M_deallocate_buckets(); + _M_reset(); + std::__alloc_on_copy(__this_alloc, __that_alloc); + __hashtable_base::operator=(__ht); + _M_bucket_count = __ht._M_bucket_count; + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __try + { + _M_assign(__ht, + [this](const __node_type* __n) + { return _M_allocate_node(__n->_M_v()); }); + } + __catch(...) + { + // _M_assign took care of deallocating all memory. Now we + // must make sure this instance remains in a usable state. + _M_reset(); + __throw_exception_again; + } + return *this; + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + + // Reuse allocated buckets and nodes. + __bucket_type* __former_buckets = nullptr; + std::size_t __former_bucket_count = _M_bucket_count; + const __rehash_state& __former_state = _M_rehash_policy._M_state(); + + if (_M_bucket_count != __ht._M_bucket_count) + { + __former_buckets = _M_buckets; + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); + _M_bucket_count = __ht._M_bucket_count; + } + else + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + + __try + { + __hashtable_base::operator=(__ht); + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __detail::_ReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits> + __roan(_M_begin(), *this); + _M_before_begin()._M_nxt = nullptr; + _M_assign(__ht, __roan); + if (__former_buckets) + _M_deallocate_buckets(__former_buckets, __former_bucket_count); + } + __catch(...) + { + if (__former_buckets) + { + // Restore previous buckets. + _M_deallocate_buckets(); + _M_rehash_policy._M_reset(__former_state); + _M_buckets = __former_buckets; + _M_bucket_count = __former_bucket_count; + } + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + __throw_exception_again; + } + return *this; + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + template<typename _UnaryOp> + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_assign(const _Hashtable& __ht, const _UnaryOp& __node_getter) + { + __bucket_type* __buckets = nullptr; + if (!_M_buckets) + _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count); + + __try + { + if (!__ht._M_before_begin()._M_nxt) + return; + + // First deal with the special first node pointed to by + // _M_before_begin. + __node_type* __ht_n = __ht._M_begin(); + __node_type* __this_n = __node_getter(__ht_n); + this->_M_copy_code(__this_n, __ht_n); + _M_before_begin()._M_nxt = __this_n; + _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin(); + + // Then deal with other nodes. + __node_base* __prev_n = __this_n; + for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next()) + { + __this_n = __node_getter(__ht_n); + __prev_n->_M_nxt = __this_n; + this->_M_copy_code(__this_n, __ht_n); + size_type __bkt = _M_bucket_index(__this_n); + if (!_M_buckets[__bkt]) + _M_buckets[__bkt] = __prev_n; + __prev_n = __this_n; + } + } + __catch(...) + { + clear(); + if (__buckets) + _M_deallocate_buckets(); + __throw_exception_again; + } + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_reset() noexcept + { + _M_rehash_policy._M_reset(); + _M_bucket_count = 0; + _M_buckets = nullptr; + _M_before_begin()._M_nxt = nullptr; + _M_element_count = 0; + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, std::true_type) + { + _M_deallocate_nodes(_M_begin()); + if (__builtin_expect(_M_bucket_count != 0, true)) + _M_deallocate_buckets(); + + __hashtable_base::operator=(std::move(__ht)); + _M_rehash_policy = __ht._M_rehash_policy; + _M_buckets = __ht._M_buckets; + _M_bucket_count = __ht._M_bucket_count; + _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt; + _M_element_count = __ht._M_element_count; + std::__alloc_on_move(_M_node_allocator(), __ht._M_node_allocator()); + + // Fix buckets containing the _M_before_begin pointers that can't be + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin(); + __ht._M_reset(); + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, std::false_type) + { + if (__ht._M_node_allocator() == _M_node_allocator()) + _M_move_assign(std::move(__ht), std::true_type()); + else + { + // Can't move memory, move elements then. + __bucket_type* __former_buckets = nullptr; + size_type __former_bucket_count = _M_bucket_count; + const __rehash_state& __former_state = _M_rehash_policy._M_state(); + + if (_M_bucket_count != __ht._M_bucket_count) + { + __former_buckets = _M_buckets; + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); + _M_bucket_count = __ht._M_bucket_count; + } + else + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + + __try + { + __hashtable_base::operator=(std::move(__ht)); + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __detail::_MoveReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits> + __mroan(_M_begin(), *this); + _M_before_begin()._M_nxt = nullptr; + _M_assign(__ht, __mroan); + __ht.clear(); + } + __catch(...) + { + if (__former_buckets) + { + _M_deallocate_buckets(); + _M_rehash_policy._M_reset(__former_state); + _M_buckets = __former_buckets; + _M_bucket_count = __former_bucket_count; + } + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + __throw_exception_again; + } + } + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _Hashtable(const _Hashtable& __ht) : __hashtable_base(__ht), __map_base(__ht), __rehash_base(__ht), + _M_buckets(), _M_bucket_count(__ht._M_bucket_count), - _M_bbegin(__ht._M_bbegin), + _M_bbegin(_Node_alloc_traits::_S_select_on_copy( + __ht._M_node_allocator())), _M_element_count(__ht._M_element_count), _M_rehash_policy(__ht._M_rehash_policy) { - _M_buckets = _M_allocate_buckets(_M_bucket_count); - __try - { - if (!__ht._M_before_begin()._M_nxt) - return; - - // First deal with the special first node pointed to by - // _M_before_begin. - const __node_type* __ht_n = __ht._M_begin(); - __node_type* __this_n = _M_allocate_node(__ht_n->_M_v); - this->_M_copy_code(__this_n, __ht_n); - _M_before_begin()._M_nxt = __this_n; - _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin(); - - // Then deal with other nodes. - __node_base* __prev_n = __this_n; - for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next()) - { - __this_n = _M_allocate_node(__ht_n->_M_v); - __prev_n->_M_nxt = __this_n; - this->_M_copy_code(__this_n, __ht_n); - size_type __bkt = _M_bucket_index(__this_n); - if (!_M_buckets[__bkt]) - _M_buckets[__bkt] = __prev_n; - __prev_n = __this_n; - } - } - __catch(...) - { - clear(); - _M_deallocate_buckets(_M_buckets, _M_bucket_count); - __throw_exception_again; - } + _M_assign(__ht, + [this](const __node_type* __n) + { return _M_allocate_node(__n->_M_v()); }); } template<typename _Key, typename _Value, @@ -927,7 +1207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Traits> _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(_Hashtable&& __ht) + _Hashtable(_Hashtable&& __ht) noexcept : __hashtable_base(__ht), __map_base(__ht), __rehash_base(__ht), @@ -937,14 +1217,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_element_count(__ht._M_element_count), _M_rehash_policy(__ht._M_rehash_policy) { - // Update, if necessary, bucket pointing to before begin that hasn't moved. + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. if (_M_begin()) _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin(); - __ht._M_rehash_policy = _RehashPolicy(); - __ht._M_bucket_count = __ht._M_rehash_policy._M_next_bkt(0); - __ht._M_buckets = __ht._M_allocate_buckets(__ht._M_bucket_count); - __ht._M_before_begin()._M_nxt = nullptr; - __ht._M_element_count = 0; + __ht._M_reset(); + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(const _Hashtable& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + _M_buckets(), + _M_bucket_count(__ht._M_bucket_count), + _M_bbegin(_Node_alloc_type(__a)), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + _M_assign(__ht, + [this](const __node_type* __n) + { return _M_allocate_node(__n->_M_v()); }); + } + + template<typename _Key, typename _Value, + typename _Alloc, typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, + typename _Traits> + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_Hashtable&& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + _M_buckets(), + _M_bucket_count(__ht._M_bucket_count), + _M_bbegin(_Node_alloc_type(__a)), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + if (__ht._M_node_allocator() == _M_node_allocator()) + { + _M_buckets = __ht._M_buckets; + _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt; + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin(); + __ht._M_reset(); + } + else + { + _M_assign(__ht, + [this](__node_type* __n) + { + return _M_allocate_node( + std::move_if_noexcept(__n->_M_v())); + }); + __ht.clear(); + } } template<typename _Key, typename _Value, @@ -956,7 +1292,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~_Hashtable() noexcept { clear(); - _M_deallocate_buckets(_M_buckets, _M_bucket_count); + if (_M_buckets) + _M_deallocate_buckets(); } template<typename _Key, typename _Value, @@ -967,25 +1304,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: swap(_Hashtable& __x) + noexcept(_Node_alloc_traits::_S_nothrow_swap()) { // The only base class with member variables is hash_code_base. // We define _Hash_code_base::_M_swap because different // specializations have different members. this->_M_swap(__x); - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 431. Swapping containers with unequal allocators. - std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator(), - __x._M_node_allocator()); - + std::__alloc_on_swap(_M_node_allocator(), __x._M_node_allocator()); std::swap(_M_rehash_policy, __x._M_rehash_policy); std::swap(_M_buckets, __x._M_buckets); std::swap(_M_bucket_count, __x._M_bucket_count); std::swap(_M_before_begin()._M_nxt, __x._M_before_begin()._M_nxt); std::swap(_M_element_count, __x._M_element_count); - // Fix buckets containing the _M_before_begin pointers that - // can't be swapped. + // Fix buckets containing the _M_before_begin pointers that can't be + // swapped. if (_M_begin()) _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin(); if (__x._M_begin()) @@ -1020,10 +1354,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: find(const key_type& __k) { + if (__builtin_expect(_M_bucket_count == 0, false)) + return end(); + __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); - return __p ? iterator(__p) : this->end(); + return __p ? iterator(__p) : end(); } template<typename _Key, typename _Value, @@ -1037,10 +1374,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: find(const key_type& __k) const { + if (__builtin_expect(_M_bucket_count == 0, false)) + return end(); + __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); - return __p ? const_iterator(__p) : this->end(); + return __p ? const_iterator(__p) : end(); } template<typename _Key, typename _Value, @@ -1054,6 +1394,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: count(const key_type& __k) const { + if (__builtin_expect(_M_bucket_count == 0, false)) + return 0; + __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_bucket_begin(__n); @@ -1092,6 +1435,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: equal_range(const key_type& __k) { + if (__builtin_expect(_M_bucket_count == 0, false)) + return std::make_pair(end(), end()); + __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1106,7 +1452,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::make_pair(iterator(__p), iterator(__p1)); } else - return std::make_pair(this->end(), this->end()); + return std::make_pair(end(), end()); } template<typename _Key, typename _Value, @@ -1125,6 +1471,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: equal_range(const key_type& __k) const { + if (__builtin_expect(_M_bucket_count == 0, false)) + return std::make_pair(end(), end()); + __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1139,7 +1488,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::make_pair(const_iterator(__p), const_iterator(__p1)); } else - return std::make_pair(this->end(), this->end()); + return std::make_pair(end(), end()); } // Find the node whose key compares equal to k in the bucket n. @@ -1258,7 +1607,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // First build the node to get access to the hash code __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...); - const key_type& __k = this->_M_extract()(__node->_M_v); + const key_type& __k = this->_M_extract()(__node->_M_v()); __hash_code __code; __try { @@ -1301,7 +1650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __hash_code __code; __try { - __code = this->_M_hash_code(this->_M_extract()(__node->_M_v)); + __code = this->_M_hash_code(this->_M_extract()(__node->_M_v())); } __catch(...) { @@ -1333,7 +1682,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__do_rehash.first) { _M_rehash(__do_rehash.second, __saved_state); - __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v), __code); + __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code); } this->_M_store_code(__node, __code); @@ -1373,7 +1722,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_rehash(__do_rehash.second, __saved_state); this->_M_store_code(__node, __code); - const key_type& __k = this->_M_extract()(__node->_M_v); + const key_type& __k = this->_M_extract()(__node->_M_v()); size_type __bkt = _M_bucket_index(__k, __code); // Find the node before an equivalent one. @@ -1722,7 +2071,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __p = __next; } - _M_deallocate_buckets(_M_buckets, _M_bucket_count); + + if (__builtin_expect(_M_bucket_count != 0, true)) + _M_deallocate_buckets(); _M_bucket_count = __n; _M_buckets = __new_buckets; } @@ -1812,7 +2163,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __new_buckets[__next_bkt] = __prev_p; } - _M_deallocate_buckets(_M_buckets, _M_bucket_count); + if (__builtin_expect(_M_bucket_count != 0, true)) + _M_deallocate_buckets(); _M_bucket_count = __n; _M_buckets = __new_buckets; } diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index f75f49fcd6d..1c76af0ac66 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -156,6 +156,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; /** + * struct _Hash_node_value_base + * + * Node type with the value to store. + */ + template<typename _Value> + struct _Hash_node_value_base : _Hash_node_base + { + __gnu_cxx::__aligned_buffer<_Value> _M_storage; + + _Value* + _M_valptr() noexcept + { return _M_storage._M_ptr(); } + + const _Value* + _M_valptr() const noexcept + { return _M_storage._M_ptr(); } + + _Value& + _M_v() noexcept + { return *_M_valptr(); } + + const _Value& + _M_v() const noexcept + { return *_M_valptr(); } + }; + + /** * Primary template struct _Hash_node. */ template<typename _Value, bool _Cache_hash_code> @@ -164,38 +191,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Specialization for nodes with caches, struct _Hash_node. * - * Base class is __detail::_Hash_node_base. + * Base class is __detail::_Hash_node_value_base. */ template<typename _Value> - struct _Hash_node<_Value, true> : _Hash_node_base + struct _Hash_node<_Value, true> : _Hash_node_value_base<_Value> { - _Value _M_v; std::size_t _M_hash_code; - template<typename... _Args> - _Hash_node(_Args&&... __args) - : _M_v(std::forward<_Args>(__args)...), _M_hash_code() { } - _Hash_node* - _M_next() const { return static_cast<_Hash_node*>(_M_nxt); } + _M_next() const { return static_cast<_Hash_node*>(this->_M_nxt); } }; /** * Specialization for nodes without caches, struct _Hash_node. * - * Base class is __detail::_Hash_node_base. + * Base class is __detail::_Hash_node_value_base. */ template<typename _Value> - struct _Hash_node<_Value, false> : _Hash_node_base + struct _Hash_node<_Value, false> : _Hash_node_value_base<_Value> { - _Value _M_v; - - template<typename... _Args> - _Hash_node(_Args&&... __args) - : _M_v(std::forward<_Args>(__args)...) { } - _Hash_node* - _M_next() const { return static_cast<_Hash_node*>(_M_nxt); } + _M_next() const { return static_cast<_Hash_node*>(this->_M_nxt); } }; /// Base class for node iterators. @@ -255,11 +271,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reference operator*() const - { return this->_M_cur->_M_v; } + { return this->_M_cur->_M_v(); } pointer operator->() const - { return std::__addressof(this->_M_cur->_M_v); } + { return this->_M_cur->_M_valptr(); } _Node_iterator& operator++() @@ -307,11 +323,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reference operator*() const - { return this->_M_cur->_M_v; } + { return this->_M_cur->_M_v(); } pointer operator->() const - { return std::__addressof(this->_M_cur->_M_v); } + { return this->_M_cur->_M_valptr(); } _Node_const_iterator& operator++() @@ -341,7 +357,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef std::size_t result_type; result_type - operator()(first_argument_type __num, second_argument_type __den) const + operator()(first_argument_type __num, + second_argument_type __den) const noexcept { return __num % __den; } }; @@ -387,6 +404,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_next_resize; } void + _M_reset() noexcept + { _M_next_resize = 0; } + + void _M_reset(_State __state) { _M_next_resize = __state; } @@ -496,7 +517,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __h->_M_insert_unique_node(__n, __code, __p)->second; } - return (__p->_M_v).second; + return __p->_M_v().second; } template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, @@ -522,7 +543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __h->_M_insert_unique_node(__n, __code, __p)->second; } - return (__p->_M_v).second; + return __p->_M_v().second; } template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, @@ -542,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (!__p) __throw_out_of_range(__N("_Map_base::at")); - return (__p->_M_v).second; + return __p->_M_v().second; } template<typename _Key, typename _Pair, typename _Alloc, typename _Equal, @@ -562,7 +583,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (!__p) __throw_out_of_range(__N("_Map_base::at")); - return (__p->_M_v).second; + return __p->_M_v().second; } /** @@ -644,7 +665,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __h._M_rehash(__do_rehash.second, __saved_state); for (; __first != __last; ++__first) - this->insert(*__first); + __h._M_insert(*__first, __unique_keys()); } /** @@ -823,8 +844,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Primary class template _Hashtable_ebo_helper. * - * Helper class using EBO when it is not forbidden, type is not - * final, and when it worth it, type is empty. + * Helper class using EBO when it is not forbidden (the type is not + * final) and when it is worth it (the type is empty.) */ template<int _Nm, typename _Tp, bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> @@ -939,7 +960,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t _M_bucket_index(const __node_type* __p, std::size_t __n) const - { return _M_ranged_hash()(_M_extract()(__p->_M_v), __n); } + noexcept( noexcept(declval<const _Hash&>()(declval<const _Key&>(), (std::size_t)0)) ) + { return _M_ranged_hash()(_M_extract()(__p->_M_v()), __n); } void _M_store_code(__node_type*, __hash_code) const @@ -1023,9 +1045,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_h2()(__c, __n); } std::size_t - _M_bucket_index(const __node_type* __p, - std::size_t __n) const - { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v)), __n); } + _M_bucket_index(const __node_type* __p, std::size_t __n) const + noexcept( noexcept(declval<const _H1&>()(declval<const _Key&>())) + && noexcept(declval<const _H2&>()((__hash_code)0, (std::size_t)0)) ) + { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v())), __n); } void _M_store_code(__node_type*, __hash_code) const @@ -1109,6 +1132,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t _M_bucket_index(const __node_type* __p, std::size_t __n) const + noexcept( noexcept(declval<const _H2&>()((__hash_code)0, + (std::size_t)0)) ) { return _M_h2()(__p->_M_hash_code, __n); } void @@ -1163,7 +1188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static bool _S_equals(const _Equal& __eq, const _ExtractKey& __extract, const _Key& __k, _HashCodeType __c, _Hash_node<_Value, true>* __n) - { return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v)); } + { return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v())); } }; /// Specialization. @@ -1174,7 +1199,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static bool _S_equals(const _Equal& __eq, const _ExtractKey& __extract, const _Key& __k, _HashCodeType, _Hash_node<_Value, false>* __n) - { return __eq(__k, __extract(__n->_M_v)); } + { return __eq(__k, __extract(__n->_M_v())); } }; @@ -1305,11 +1330,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reference operator*() const - { return this->_M_cur->_M_v; } + { return this->_M_cur->_M_v(); } pointer operator->() const - { return std::__addressof(this->_M_cur->_M_v); } + { return this->_M_cur->_M_valptr(); } _Local_iterator& operator++() @@ -1364,11 +1389,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reference operator*() const - { return this->_M_cur->_M_v; } + { return this->_M_cur->_M_v(); } pointer operator->() const - { return std::__addressof(this->_M_cur->_M_v); } + { return this->_M_cur->_M_valptr(); } _Local_const_iterator& operator++() @@ -1662,6 +1687,120 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { } }; + /* + * Following are functors recyclicing a pool of nodes and using allocation + * once the pool is empty. + */ + /// Version using copy semantic through the copy constructor. + template<typename _Key, typename _Value, typename _Alloc, + typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> + struct _ReuseOrAllocNode + { + private: + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + using __val_alloc_type = typename __hashtable::_Value_alloc_type; + using __val_alloc_traits = typename __hashtable::_Value_alloc_traits; + using __node_alloc_traits = typename __hashtable::_Node_alloc_traits; + using __node_type = typename __hashtable::__node_type; + + public: + _ReuseOrAllocNode(__node_type* __nodes, __hashtable& __h) + : _M_nodes(__nodes), _M_h(__h) { } + _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete; + + ~_ReuseOrAllocNode() + { _M_h._M_deallocate_nodes(_M_nodes); } + + __node_type* + operator()(const __node_type* __n) const + { + if (_M_nodes) + { + __node_type* __node = _M_nodes; + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + __val_alloc_type __a(_M_h._M_node_allocator()); + __val_alloc_traits::destroy(__a, __node->_M_valptr()); + __try + { + __val_alloc_traits::construct(__a, __node->_M_valptr(), + __n->_M_v()); + } + __catch(...) + { + __node->~__node_type(); + __node_alloc_traits::deallocate(_M_h._M_node_allocator(), + __node, 1); + __throw_exception_again; + } + return __node; + } + return _M_h._M_allocate_node(__n->_M_v()); + } + + mutable __node_type* _M_nodes; + __hashtable& _M_h; + }; + + /// Version using move semantic through the move constructor. + template<typename _Key, typename _Value, typename _Alloc, + typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> + struct _MoveReuseOrAllocNode + { + private: + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + using __val_alloc_type = typename __hashtable::_Value_alloc_type; + using __val_alloc_traits = typename __hashtable::_Value_alloc_traits; + using __node_alloc_traits = typename __hashtable::_Node_alloc_traits; + using __node_type = typename __hashtable::__node_type; + + public: + _MoveReuseOrAllocNode(__node_type* __nodes, __hashtable& __h) + : _M_nodes(__nodes), _M_h(__h) { } + _MoveReuseOrAllocNode(const _MoveReuseOrAllocNode&) = delete; + + ~_MoveReuseOrAllocNode() + { _M_h._M_deallocate_nodes(_M_nodes); } + + __node_type* + operator()(__node_type* __n) const + { + if (_M_nodes) + { + __node_type* __node = _M_nodes; + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + __val_alloc_type __a(_M_h._M_node_allocator()); + __val_alloc_traits::destroy(__a, __node->_M_valptr()); + __try + { + __val_alloc_traits::construct(__a, __node->_M_valptr(), + std::move_if_noexcept(__n->_M_v())); + } + __catch(...) + { + __node->~__node_type(); + __node_alloc_traits::deallocate(_M_h._M_node_allocator(), + __node, 1); + __throw_exception_again; + } + return __node; + } + return _M_h._M_allocate_node(std::move_if_noexcept(__n->_M_v())); + } + + mutable __node_type* _M_nodes; + __hashtable& _M_h; + }; + //@} hashtable-detail _GLIBCXX_END_NAMESPACE_VERSION } // namespace __detail diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc index 21a6a76b358..9fc43cfe68a 100644 --- a/libstdc++-v3/include/bits/list.tcc +++ b/libstdc++-v3/include/bits/list.tcc @@ -106,10 +106,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + erase(const_iterator __position) +#else erase(iterator __position) +#endif { iterator __ret = iterator(__position._M_node->_M_next); +#if __cplusplus >= 201103L + _M_erase(__position._M_const_cast()); +#else _M_erase(__position); +#endif return __ret; } diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index fb6c61fcc0a..d54edcd4168 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -116,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * type is copyable, in which case an lvalue-reference is returned instead. */ template<typename _Tp> - inline constexpr typename + constexpr typename conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type move_if_noexcept(_Tp& __x) noexcept { return std::move(__x); } diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h new file mode 100644 index 00000000000..eaa3d27a18a --- /dev/null +++ b/libstdc++-v3/include/bits/parse_numbers.h @@ -0,0 +1,417 @@ +// Components for compile-time parsing of numbers -*- C++ -*- + +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file bits/parse_numbers.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{chrono} + */ + +#ifndef _PARSE_NUMBERS_H +#define _PARSE_NUMBERS_H 1 + +#pragma GCC system_header + +// From n3642.pdf except I added binary literals and digit separator '`'. + +#if __cplusplus > 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __parse_int { + + template<unsigned _Base, char _Dig> + struct _Digit; + + template<unsigned _Base> + struct _Digit<_Base, '0'> + { + static constexpr bool valid{true}; + static constexpr unsigned value{0}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '1'> + { + static constexpr bool valid{true}; + static constexpr unsigned value{1}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '2'> + { + static_assert(_Base > 2, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{2}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '3'> + { + static_assert(_Base > 3, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{3}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '4'> + { + static_assert(_Base > 4, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{4}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '5'> + { + static_assert(_Base > 5, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{5}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '6'> + { + static_assert(_Base > 6, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{6}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '7'> + { + static_assert(_Base > 7, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{7}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '8'> + { + static_assert(_Base > 8, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{8}; + }; + + template<unsigned _Base> + struct _Digit<_Base, '9'> + { + static_assert(_Base > 9, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{9}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'a'> + { + static_assert(_Base > 0xa, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xa}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'A'> + { + static_assert(_Base > 0xa, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xa}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'b'> + { + static_assert(_Base > 0xb, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xb}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'B'> + { + static_assert(_Base > 0xb, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xb}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'c'> + { + static_assert(_Base > 0xc, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xc}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'C'> + { + static_assert(_Base > 0xc, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xc}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'd'> + { + static_assert(_Base > 0xd, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xd}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'D'> + { + static_assert(_Base > 0xd, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xd}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'e'> + { + static_assert(_Base > 0xe, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xe}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'E'> + { + static_assert(_Base > 0xe, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xe}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'f'> + { + static_assert(_Base > 0xf, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xf}; + }; + + template<unsigned _Base> + struct _Digit<_Base, 'F'> + { + static_assert(_Base > 0xf, "invalid digit"); + static constexpr bool valid{true}; + static constexpr unsigned value{0xf}; + }; + + // Digit separator + template<unsigned _Base> + struct _Digit<_Base, '`'> + { + static constexpr bool valid{false}; + static constexpr unsigned value{0}; + }; + + +//------------------------------------------------------------------------------ + + template<unsigned _Base, char _Dig, char... _Digs> + struct _Digits_help + { + static constexpr unsigned + value{_Digit<_Base, _Dig>::valid ? + 1U + _Digits_help<_Base, _Digs...>::value : + _Digits_help<_Base, _Digs...>::value}; + }; + + template<unsigned _Base, char _Dig> + struct _Digits_help<_Base, _Dig> + { + static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; + }; + + template<unsigned _Base, char... _Digs> + struct _Digits + { + static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value}; + }; + + template<unsigned _Base> + struct _Digits<_Base> + { + static constexpr unsigned value{0U}; + }; + +//------------------------------------------------------------------------------ + + template<unsigned _Base, char _Dig, char... _Digs> + struct _Power_help + { + static constexpr unsigned + value{_Digit<_Base, _Dig>::valid ? + _Base * _Power_help<_Base, _Digs...>::value : + _Power_help<_Base, _Digs...>::value}; + }; + + template<unsigned _Base, char _Dig> + struct _Power_help<_Base, _Dig> + { + static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; + }; + + template<unsigned _Base, char... _Digs> + struct _Power + { + static constexpr unsigned value{_Power_help<_Base, _Digs...>::value}; + }; + + template<unsigned _Base> + struct _Power<_Base> + { + static constexpr unsigned value{0U}; + }; + +//------------------------------------------------------------------------------ + + template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs> + struct _Number_help + { + static constexpr unsigned + value{_Digit<_Base, _Dig>::valid ? + _Pow * _Digit<_Base, _Dig>::value + + _Number_help<_Base, _Pow / _Base, _Digs...>::value : + _Number_help<_Base, _Pow, _Digs...>::value}; + }; + + template<unsigned _Base, unsigned _Pow, char _Dig> + struct _Number_help<_Base, _Pow, _Dig> + { + //static_assert(_Pow == 1U, "power should be one"); + static constexpr unsigned + value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U}; + }; + + template<unsigned _Base, char... _Digs> + struct _Number + { + static constexpr unsigned + value{_Number_help<_Base, _Power<_Base, _Digs...>::value, + _Digs...>::value}; + }; + + template<unsigned _Base> + struct _Number<_Base> + { + static constexpr unsigned value{0U}; + }; + +//------------------------------------------------------------------------------ +// This _Parse_int is the same 'level' as the old _Base_dispatch. + + template<char... _Digs> + struct _Parse_int; + + template<char... _Digs> + struct _Parse_int<'0', 'b', _Digs...> + { + static constexpr unsigned long long + value{_Number<2U, _Digs...>::value}; + }; + + template<char... _Digs> + struct _Parse_int<'0', 'B', _Digs...> + { + static constexpr unsigned long long + value{_Number<2U, _Digs...>::value}; + }; + + template<char... _Digs> + struct _Parse_int<'0', 'x', _Digs...> + { + static constexpr unsigned long long + value{_Number<16U, _Digs...>::value}; + }; + + template<char... _Digs> + struct _Parse_int<'0', 'X', _Digs...> + { + static constexpr unsigned long long + value{_Number<16U, _Digs...>::value}; + }; + + template<char... _Digs> + struct _Parse_int<'0', _Digs...> + { + static constexpr unsigned long long + value{_Number<8U, _Digs...>::value}; + }; + + template<char... _Digs> + struct _Parse_int + { + static constexpr unsigned long long + value{_Number<10U, _Digs...>::value}; + }; + +} // namespace __parse_int + + +namespace __select_int { + + template<unsigned long long _Val, typename... _Ints> + struct _Select_int_base; + + template<unsigned long long _Val, typename _IntType, typename... _Ints> + struct _Select_int_base<_Val, _IntType, _Ints...> + : integral_constant + < + typename conditional + < + _Val <= static_cast<unsigned long long> + (std::numeric_limits<_IntType>::max()), + _IntType, + typename _Select_int_base<_Val, _Ints...>::value_type + >::type, + _Val + > + { }; + + template<unsigned long long _Val> + struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val> + { }; + + template<char... _Digs> + struct _Select_int + : _Select_int_base< + __parse_int::_Parse_int<_Digs...>::value, + unsigned char, + unsigned short, + unsigned int, + unsigned long, + unsigned long long + > + { }; + +} // namespace __select_int + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus > 201103L + +#endif // _PARSE_NUMBERS_H diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index b471726be55..caabe906058 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -3978,7 +3978,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _UniformRandomNumberGenerator> result_type - _M_waiting(_UniformRandomNumberGenerator& __urng, _IntType __t); + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q); param_type _M_param; diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 5b562b9f270..c6db5b40cb7 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -1648,7 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _UniformRandomNumberGenerator> typename binomial_distribution<_IntType>::result_type binomial_distribution<_IntType>:: - _M_waiting(_UniformRandomNumberGenerator& __urng, _IntType __t) + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q) { _IntType __x = 0; double __sum = 0.0; @@ -1663,7 +1664,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __sum += __e / (__t - __x); __x += 1; } - while (__sum <= _M_param._M_q); + while (__sum <= __q); return __x - 1; } @@ -1784,12 +1785,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __x += __np + __naf; - const _IntType __z = _M_waiting(__urng, __t - _IntType(__x)); + const _IntType __z = _M_waiting(__urng, __t - _IntType(__x), + __param._M_q); __ret = _IntType(__x) + __z; } else #endif - __ret = _M_waiting(__urng, __t); + __ret = _M_waiting(__urng, __t, __param._M_q); if (__p12 != __p) __ret = __t - __ret; diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 71f1b692a18..3a99cff0061 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -60,7 +60,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ - /// 2.2.3.7 shared_ptr I/O + /// 20.7.2.2.11 shared_ptr I/O template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp> inline std::basic_ostream<_Ch, _Tr>& operator<<(std::basic_ostream<_Ch, _Tr>& __os, @@ -70,7 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __os; } - /// 2.2.3.10 shared_ptr get_deleter (experimental) + /// 20.7.2.2.10 shared_ptr get_deleter template<typename _Del, typename _Tp, _Lock_policy _Lp> inline _Del* get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index c5df1fbcacc..fb19d0887dc 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -49,6 +49,8 @@ #ifndef _SHARED_PTR_BASE_H #define _SHARED_PTR_BASE_H 1 +#include <ext/aligned_buffer.h> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -124,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { delete this; } virtual void* - _M_get_deleter(const std::type_info&) = 0; + _M_get_deleter(const std::type_info&) noexcept = 0; void _M_add_ref_copy() @@ -282,7 +284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: explicit - _Sp_counted_ptr(_Ptr __p) + _Sp_counted_ptr(_Ptr __p) noexcept : _M_ptr(__p) { } virtual void @@ -294,14 +296,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { delete this; } virtual void* - _M_get_deleter(const std::type_info&) - { return 0; } + _M_get_deleter(const std::type_info&) noexcept + { return nullptr; } _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; - protected: - _Ptr _M_ptr; // copy constructor must not throw + private: + _Ptr _M_ptr; }; template<> @@ -316,59 +318,91 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline void _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { } + template<int _Nm, typename _Tp, + bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> + struct _Sp_ebo_helper; + + /// Specialization using EBO. + template<int _Nm, typename _Tp> + struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp + { + explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { } + + static _Tp& + _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); } + }; + + /// Specialization not using EBO. + template<int _Nm, typename _Tp> + struct _Sp_ebo_helper<_Nm, _Tp, false> + { + explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { } + + static _Tp& + _S_get(_Sp_ebo_helper& __eboh) + { return __eboh._M_tp; } + + private: + _Tp _M_tp; + }; + // Support for custom deleter and/or allocator template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> class _Sp_counted_deleter final : public _Sp_counted_base<_Lp> { - // Helper class that stores the Deleter and also acts as an allocator. - // Used to dispose of the owned pointer and the internal refcount - // Requires that copies of _Alloc can free each other's memory. - struct _My_Deleter - : public _Alloc // copy constructor must not throw + class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc> { - _Deleter _M_del; // copy constructor must not throw - _My_Deleter(_Deleter __d, const _Alloc& __a) - : _Alloc(__a), _M_del(__d) { } + typedef _Sp_ebo_helper<0, _Deleter> _Del_base; + typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base; + + public: + _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept + : _M_ptr(__p), _Del_base(__d), _Alloc_base(__a) + { } + + _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); } + _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); } + + _Ptr _M_ptr; }; public: // __d(__p) must not throw. - _Sp_counted_deleter(_Ptr __p, _Deleter __d) - : _M_ptr(__p), _M_del(__d, _Alloc()) { } + _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept + : _M_impl(__p, __d, _Alloc()) { } // __d(__p) must not throw. - _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) - : _M_ptr(__p), _M_del(__d, __a) { } + _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept + : _M_impl(__p, __d, __a) { } ~_Sp_counted_deleter() noexcept { } virtual void _M_dispose() noexcept - { _M_del._M_del(_M_ptr); } + { _M_impl._M_del()(_M_impl._M_ptr); } virtual void _M_destroy() noexcept { typedef typename allocator_traits<_Alloc>::template rebind_traits<_Sp_counted_deleter> _Alloc_traits; - typename _Alloc_traits::allocator_type __a(_M_del); + typename _Alloc_traits::allocator_type __a(_M_impl._M_alloc()); _Alloc_traits::destroy(__a, this); _Alloc_traits::deallocate(__a, this, 1); } virtual void* - _M_get_deleter(const std::type_info& __ti) + _M_get_deleter(const std::type_info& __ti) noexcept { #ifdef __GXX_RTTI - return __ti == typeid(_Deleter) ? &_M_del._M_del : 0; + return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr; #else - return 0; + return nullptr; #endif } - protected: - _Ptr _M_ptr; // copy constructor must not throw - _My_Deleter _M_del; // copy constructor must not throw + private: + _Impl _M_impl; }; // helpers for make_shared / allocate_shared @@ -378,25 +412,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Alloc, _Lock_policy _Lp> class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp> { - // Helper class that stores the pointer and also acts as an allocator. - // Used to dispose of the owned pointer and the internal refcount - // Requires that copies of _Alloc can free each other's memory. - struct _Impl - : public _Alloc // copy constructor must not throw + class _Impl : _Sp_ebo_helper<0, _Alloc> { - _Impl(_Alloc __a) : _Alloc(__a), _M_ptr() { } - _Tp* _M_ptr; + typedef _Sp_ebo_helper<0, _Alloc> _A_base; + + public: + explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { } + + _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); } + + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; }; public: template<typename... _Args> _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) - : _M_impl(__a), _M_storage() + : _M_impl(__a) { - _M_impl._M_ptr = static_cast<_Tp*>(static_cast<void*>(&_M_storage)); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2070. allocate_shared should use allocator_traits<A>::construct - allocator_traits<_Alloc>::construct(__a, _M_impl._M_ptr, + allocator_traits<_Alloc>::construct(__a, _M_ptr(), std::forward<_Args>(__args)...); // might throw } @@ -404,7 +439,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual void _M_dispose() noexcept - { allocator_traits<_Alloc>::destroy(_M_impl, _M_impl._M_ptr); } + { + allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr()); + } // Override because the allocator needs to know the dynamic type virtual void @@ -412,7 +449,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename allocator_traits<_Alloc>::template rebind_traits<_Sp_counted_ptr_inplace> _Alloc_traits; - typename _Alloc_traits::allocator_type __a(_M_impl); + typename _Alloc_traits::allocator_type __a(_M_impl._M_alloc()); _Alloc_traits::destroy(__a, this); _Alloc_traits::deallocate(__a, this, 1); } @@ -422,20 +459,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_get_deleter(const std::type_info& __ti) noexcept { #ifdef __GXX_RTTI - return __ti == typeid(_Sp_make_shared_tag) - ? static_cast<void*>(&_M_storage) - : 0; + return __ti == typeid(_Sp_make_shared_tag) ? _M_ptr() : nullptr; #else - return 0; + return nullptr; #endif } private: + _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); } + _Impl _M_impl; - typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type - _M_storage; }; + template<_Lock_policy _Lp> class __shared_count { @@ -593,7 +629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void* _M_get_deleter(const std::type_info& __ti) const noexcept - { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; } + { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; } bool _M_less(const __shared_count& __rhs) const noexcept @@ -1168,13 +1204,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public _Sp_less<__shared_ptr<_Tp, _Lp>> { }; - // 2.2.3.8 shared_ptr specialized algorithms. + // 20.7.2.2.8 shared_ptr specialized algorithms. template<typename _Tp, _Lock_policy _Lp> inline void swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept { __a.swap(__b); } - // 2.2.3.9 shared_ptr casts + // 20.7.2.2.9 shared_ptr casts // The seemingly equivalent code: // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get())) diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 873005b8b1a..9d6b466cf2e 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -4371,6 +4371,140 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return true; } +#if __cplusplus > 201103L + /** + * @brief Checks whether a permutaion of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, begin) returns true; + * otherwise, returns false. + */ + template<typename _ForwardIterator1, typename _ForwardIterator2> + bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + using _Cat1 + = typename iterator_traits<_ForwardIterator1>::iterator_category; + using _Cat2 + = typename iterator_traits<_ForwardIterator2>::iterator_category; + using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; + using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; + if (_It1_is_RA() && _It2_is_RA()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) + if (!(*__first1 == *__first2)) + break; + + if (__first1 == __last1 && __first2 == __last2) + return true; + + if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) + return false; + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != _GLIBCXX_STD_A::find(__first1, __scan, *__scan)) + continue; // We've seen this one before. + + auto __matches = std::count(__first2, __last2, *__scan); + if (0 == __matches + || std::count(__scan, __last1, *__scan) != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template<typename _ForwardIterator1, typename _ForwardIterator2, + typename _BinaryPredicate> + bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + using _Cat1 + = typename iterator_traits<_ForwardIterator1>::iterator_category; + using _Cat2 + = typename iterator_traits<_ForwardIterator2>::iterator_category; + using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; + using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; + constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); + if (__ra_iters) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1; ++__first1, ++__first2) + if (!bool(__pred(*__first1, *__first2))) + break; + + if (__ra_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + using std::placeholders::_1; + + if (__scan != _GLIBCXX_STD_A::find_if(__first1, __scan, + std::bind(__pred, _1, *__scan))) + continue; // We've seen this one before. + + auto __matches = std::count_if(__first2, __last2, + std::bind(__pred, _1, *__scan)); + if (0 == __matches + || std::count_if(__scan, __last1, + std::bind(__pred, _1, *__scan)) != __matches) + return false; + } + return true; + } +#endif + #ifdef _GLIBCXX_USE_C99_STDINT_TR1 /** * @brief Shuffle the elements of a sequence using a uniform random diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index a90881f8f62..e1daac2ddda 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -827,7 +827,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__equal<__simple>::equal(__first1, __last1, __first2); } - template<typename, typename> struct __lc_rai { @@ -1064,6 +1063,99 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return true; } +#if __cplusplus > 201103L + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template<typename _II1, typename _II2> + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return std::equal(__first1, __last1, __first2); + } + + for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) + if (!(*__first1 == *__first2)) + return false; + return __first1 == __last1 && __first2 == __last2; + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template<typename _IIter1, typename _IIter2, typename _BinaryPredicate> + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_IIter1>::iterator_category; + using _Cat2 = typename iterator_traits<_IIter2>::iterator_category; + using _RAIters = __and_<is_same<_Cat1, _RATag>, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return std::equal(__first1, __last1, __first2, __binary_pred); + } + + for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } +#endif + /** * @brief Performs @b dictionary comparison on ranges. * @ingroup sorting_algorithms @@ -1211,6 +1303,84 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return pair<_InputIterator1, _InputIterator2>(__first1, __first2); } +#if __cplusplus > 201103L + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template<typename _InputIterator1, typename _InputIterator2> + pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + while (__first1 != __last1 && __first2 != __last2 + && *__first1 == *__first2) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template<typename _InputIterator1, typename _InputIterator2, + typename _BinaryPredicate> + pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + while (__first1 != __last1 && __first2 != __last2 + && bool(__binary_pred(*__first1, *__first2))) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } +#endif + _GLIBCXX_END_NAMESPACE_ALGO } // namespace std diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 670b19502af..97424fa7a7d 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -308,6 +308,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Bit_const_iterator(const _Bit_iterator& __x) : _Bit_iterator_base(__x._M_p, __x._M_offset) { } + _Bit_iterator + _M_const_cast() const + { return _Bit_iterator(_M_p, _M_offset); } + const_reference operator*() const { return _Bit_reference(_M_p, 1UL << _M_offset); } @@ -898,21 +902,22 @@ template<typename _Alloc> { --this->_M_impl._M_finish; } iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) + { return _M_erase(__position._M_const_cast()); } +#else erase(iterator __position) - { - if (__position + 1 != end()) - std::copy(__position + 1, end(), __position); - --this->_M_impl._M_finish; - return __position; - } + { return _M_erase(__position); } +#endif iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } +#else erase(iterator __first, iterator __last) - { - if (__first != __last) - _M_erase_at_end(std::copy(__last, end(), __first)); - return __first; - } + { return _M_erase(__first, __last); } +#endif void resize(size_type __new_size, bool __x = bool()) @@ -1124,6 +1129,12 @@ template<typename _Alloc> void _M_erase_at_end(iterator __pos) { this->_M_impl._M_finish = __pos; } + + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); }; _GLIBCXX_END_NAMESPACE_CONTAINER diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index d07bc4d29f3..4bea82b1807 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -136,6 +136,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_cur(__x._M_cur), _M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) { } + iterator + _M_const_cast() const + { return iterator(_M_cur, _M_node); } + reference operator*() const { return *_M_cur; } @@ -1562,7 +1566,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Managing the pointer is the user's responsibility. */ iterator - erase(iterator __position); +#if __cplusplus >= 201103L + erase(const_iterator __position) + { return _M_erase(__position._M_const_cast()); } +#else + erase(iterator __position) + { return _M_erase(__position); } +#endif /** * @brief Remove a range of elements. @@ -1581,7 +1591,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * way. Managing the pointer is the user's responsibility. */ iterator - erase(iterator __first, iterator __last); +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } +#else + erase(iterator __first, iterator __last) + { return _M_erase(__first, __last); } +#endif /** * @brief Swaps data with another %deque. @@ -1873,6 +1889,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_finish = __pos; } + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); + #if __cplusplus >= 201103L // Called by resize(sz). void diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h index de097800144..807a8cf0525 100644 --- a/libstdc++-v3/include/bits/stl_heap.h +++ b/libstdc++-v3/include/bits/stl_heap.h @@ -291,8 +291,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_heap(__first, __last); - --__last; - std::__pop_heap(__first, __last, __last); + if (__last - __first > 1) + { + --__last; + std::__pop_heap(__first, __last, __last); + } } template<typename _RandomAccessIterator, typename _Distance, @@ -363,8 +366,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_non_empty_range(__first, __last); __glibcxx_requires_heap_pred(__first, __last, __comp); - --__last; - std::__pop_heap(__first, __last, __last, __comp); + if (__last - __first > 1) + { + --__last; + std::__pop_heap(__first, __last, __last, __comp); + } } /** diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 214f37ff6e6..50b55eb57b4 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -63,6 +63,7 @@ #include <bits/cpp_type_traits.h> #include <ext/type_traits.h> #include <bits/move.h> +#include <bits/ptr_traits.h> namespace std _GLIBCXX_VISIBILITY(default) { @@ -733,6 +734,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Container>::__type>& __i) : _M_current(__i.base()) { } + __normal_iterator<typename _Container::pointer, _Container> + _M_const_cast() const + { +#if __cplusplus >= 201103L + using _PTraits = std::pointer_traits<typename _Container::pointer>; + return __normal_iterator<typename _Container::pointer, _Container> + (_PTraits::pointer_to(const_cast<typename _PTraits::element_type&> + (*_M_current))); +#else + return __normal_iterator<typename _Container::pointer, _Container> + (const_cast<typename _Container::pointer>(_M_current)); +#endif + } + // Forward iterator requirements reference operator*() const diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index cc6edb3da7f..678947107f3 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -219,6 +219,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _List_const_iterator(const iterator& __x) : _M_node(__x._M_node) { } + iterator + _M_const_cast() const + { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); } + // Must downcast from List_node_base to _List_node to get to // _M_data. reference @@ -1169,7 +1173,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * any way. Managing the pointer is the user's responsibility. */ iterator +#if __cplusplus >= 201103L + erase(const_iterator __position); +#else erase(iterator __position); +#endif /** * @brief Remove a range of elements. @@ -1190,11 +1198,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * is the user's responsibility. */ iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) +#else erase(iterator __first, iterator __last) +#endif { while (__first != __last) __first = erase(__first); +#if __cplusplus >= 201103L + return __last._M_const_cast(); +#else return __last; +#endif } /** @@ -1487,7 +1503,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __false_type) { for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else push_back(*__first); +#endif } // Called by list(n,v,a), and the range constructor when it turns out diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 1f6763cd244..d05e4b9ab7d 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -690,7 +690,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER erase(const_iterator __position) { return _M_t.erase(__position); } - // LWG 2059. + // LWG 2059 + _GLIBCXX_ABI_TAG_CXX11 iterator erase(iterator __position) { return _M_t.erase(__position); } diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 696e298aa8b..809ea540b8a 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -596,6 +596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t.erase(__position); } // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 iterator erase(iterator __position) { return _M_t.erase(__position); } diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index ea22f4c8057..8ceb02ac65f 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -532,6 +532,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * not touched in any way. Managing the pointer is the user's * responsibility. */ + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __position) { return _M_t.erase(__position); } @@ -583,6 +584,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * touched in any way. Managing the pointer is the user's * responsibility. */ + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __first, const_iterator __last) { return _M_t.erase(__first, __last); } diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index 14f9f5a1823..44eb5897f0e 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -546,6 +546,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * touched in any way. Managing the pointer is the user's * responsibility. */ + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __position) { return _M_t.erase(__position); } @@ -597,6 +598,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * the element is itself a pointer, the pointed-to memory is not touched * in any way. Managing the pointer is the user's responsibility. */ + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __first, const_iterator __last) { return _M_t.erase(__first, __last); } diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 59883fca834..91bf4df4511 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -62,6 +62,9 @@ #include <bits/allocator.h> #include <bits/stl_function.h> #include <bits/cpp_type_traits.h> +#if __cplusplus >= 201103L +#include <bits/alloc_traits.h> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -333,21 +336,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Node_allocator; protected: - typedef _Rb_tree_node_base* _Base_ptr; - typedef const _Rb_tree_node_base* _Const_Base_ptr; + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; public: - typedef _Key key_type; - typedef _Val value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef _Rb_tree_node<_Val>* _Link_type; - typedef const _Rb_tree_node<_Val>* _Const_Link_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef _Rb_tree_node<_Val>* _Link_type; + typedef const _Rb_tree_node<_Val>* _Const_Link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; _Node_allocator& _M_get_Node_allocator() _GLIBCXX_NOEXCEPT @@ -400,8 +403,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Link_type __tmp = _M_get_node(); __try { - _M_get_Node_allocator().construct(__tmp, - std::forward<_Args>(__args)...); + allocator_traits<_Node_allocator>:: + construct(_M_get_Node_allocator(), __tmp, + std::forward<_Args>(__args)...); } __catch(...) { @@ -796,6 +800,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __position) { @@ -806,6 +811,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 iterator erase(iterator __position) { @@ -829,6 +835,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 iterator erase(const_iterator __first, const_iterator __last) { diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index d880ba77905..5ac575460a0 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1072,7 +1072,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * the pointer is the user's responsibility. */ iterator - erase(iterator __position); +#if __cplusplus >= 201103L + erase(const_iterator __position) + { return _M_erase(__position._M_const_cast()); } +#else + erase(iterator __position) + { return _M_erase(__position); } +#endif /** * @brief Remove a range of elements. @@ -1093,7 +1099,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Managing the pointer is the user's responsibility. */ iterator - erase(iterator __first, iterator __last); +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } +#else + erase(iterator __first, iterator __last) + { return _M_erase(__first, __last); } +#endif /** * @brief Swaps data with another %vector. @@ -1184,7 +1196,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _InputIterator __last, std::input_iterator_tag) { for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else push_back(*__first); +#endif } // Called by the second initialize_dispatch above @@ -1349,6 +1365,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_finish = __pos; } + iterator + _M_erase(iterator __position); + + iterator + _M_erase(iterator __first, iterator __last); + #if __cplusplus >= 201103L private: // Constant-time move assignment when source object's memory can be diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 66d73b25c6a..c6c9a5a04a5 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -49,16 +49,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename> class auto_ptr; #endif - /// Primary template, default_delete. + /// Primary template of default_delete, used by unique_ptr template<typename _Tp> struct default_delete { + /// Default constructor constexpr default_delete() noexcept = default; + /** @brief Converting constructor. + * + * Allows conversion from a deleter for arrays of another type, @p _Up, + * only if @p _Up* is convertible to @p _Tp*. + */ template<typename _Up, typename = typename enable_if<is_convertible<_Up*, _Tp*>::value>::type> default_delete(const default_delete<_Up>&) noexcept { } + /// Calls @c delete @p __ptr void operator()(_Tp* __ptr) const { @@ -70,7 +77,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 740 - omit specialization for array objects with a compile time length - /// Specialization, default_delete. + /// Specialization for arrays, default_delete. template<typename _Tp> struct default_delete<_Tp[]> { @@ -85,12 +92,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; public: + /// Default constructor constexpr default_delete() noexcept = default; + /** @brief Converting constructor. + * + * Allows conversion from a deleter for arrays of another type, such as + * a const-qualified version of @p _Tp. + * + * Conversions from types derived from @c _Tp are not allowed because + * it is unsafe to @c delete[] an array of derived types through a + * pointer to the base type. + */ template<typename _Up, typename = typename enable_if<!__is_derived_Tp<_Up>::value>::type> default_delete(const default_delete<_Up[]>&) noexcept { } + /// Calls @c delete[] @p __ptr void operator()(_Tp* __ptr) const { @@ -132,34 +150,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Dp deleter_type; // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr() noexcept : _M_t() { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * + * The deleter will be value-initialized. + */ explicit unique_ptr(pointer __p) noexcept : _M_t(__p, deleter_type()) { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ unique_ptr(pointer __p, typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept : _M_t(__p, __d) { } + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d An rvalue reference to a deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d) noexcept : _M_t(std::move(__p), std::move(__d)) { static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } + /// Creates a unique_ptr that owns nothing. constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } // Move constructors. + + /// Move constructor. unique_ptr(unique_ptr&& __u) noexcept : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } + /** @brief Converting constructor from another type + * + * Requires that the pointer owned by @p __u is convertible to the + * type of pointer owned by this object, @p __u does not own an array, + * and @p __u has a compatible deleter type. + */ template<typename _Up, typename _Ep, typename = _Require< is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, __not_<is_array<_Up>>, @@ -171,12 +220,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { } #if _GLIBCXX_USE_DEPRECATED + /// Converting constructor from @c auto_ptr template<typename _Up, typename = _Require< is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> unique_ptr(auto_ptr<_Up>&& __u) noexcept; #endif - // Destructor. + /// Destructor, invokes the deleter if the stored pointer is not null. ~unique_ptr() noexcept { auto& __ptr = std::get<0>(_M_t); @@ -186,6 +236,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Assignment. + + /** @brief Move assignment operator. + * + * @param __u The object to transfer ownership from. + * + * Invokes the deleter first if this object owns a pointer. + */ unique_ptr& operator=(unique_ptr&& __u) noexcept { @@ -194,6 +251,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to a non-array object. + * + * Invokes the deleter first if this object owns a pointer. + */ template<typename _Up, typename _Ep> typename enable_if< __and_< is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, @@ -207,6 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. unique_ptr& operator=(nullptr_t) noexcept { @@ -215,6 +280,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Observers. + + /// Dereference the stored pointer. typename add_lvalue_reference<element_type>::type operator*() const { @@ -222,6 +289,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *get(); } + /// Return the stored pointer. pointer operator->() const noexcept { @@ -229,22 +297,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return get(); } + /// Return the stored pointer. pointer get() const noexcept { return std::get<0>(_M_t); } + /// Return a reference to the stored deleter. deleter_type& get_deleter() noexcept { return std::get<1>(_M_t); } + /// Return a reference to the stored deleter. const deleter_type& get_deleter() const noexcept { return std::get<1>(_M_t); } + /// Return @c true if the stored pointer is not null. explicit operator bool() const noexcept { return get() == pointer() ? false : true; } // Modifiers. + + /// Release ownership of any stored pointer. pointer release() noexcept { @@ -253,6 +327,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __p; } + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ void reset(pointer __p = pointer()) noexcept { @@ -262,6 +342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION get_deleter()(__p); } + /// Exchange the pointer and deleter with another object. void swap(unique_ptr& __u) noexcept { @@ -326,37 +407,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Dp deleter_type; // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. constexpr unique_ptr() noexcept : _M_t() { static_assert(!std::is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of @c element_type + * + * The deleter will be value-initialized. + */ explicit unique_ptr(pointer __p) noexcept : _M_t(__p, deleter_type()) { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } + // Disable construction from convertible pointer types. template<typename _Up, typename = _Require<is_pointer<pointer>, is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> explicit unique_ptr(_Up* __p) = delete; + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ unique_ptr(pointer __p, typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept : _M_t(__p, __d) { } + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ unique_ptr(pointer __p, typename remove_reference<deleter_type>::type&& __d) noexcept : _M_t(std::move(__p), std::move(__d)) { static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } - // Move constructor. + /// Move constructor. unique_ptr(unique_ptr&& __u) noexcept : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } + /// Creates a unique_ptr that owns nothing. constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } template<typename _Up, typename _Ep, @@ -369,7 +474,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) { } - // Destructor. + /// Destructor, invokes the deleter if the stored pointer is not null. ~unique_ptr() { auto& __ptr = std::get<0>(_M_t); @@ -379,6 +484,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Assignment. + + /** @brief Move assignment operator. + * + * @param __u The object to transfer ownership from. + * + * Invokes the deleter first if this object owns a pointer. + */ unique_ptr& operator=(unique_ptr&& __u) noexcept { @@ -387,6 +499,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to an array object. + * + * Invokes the deleter first if this object owns a pointer. + */ template<typename _Up, typename _Ep> typename enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type @@ -397,6 +516,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. unique_ptr& operator=(nullptr_t) noexcept { @@ -405,6 +525,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Observers. + + /// Access an element of owned array. typename std::add_lvalue_reference<element_type>::type operator[](size_t __i) const { @@ -412,22 +534,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return get()[__i]; } + /// Return the stored pointer. pointer get() const noexcept { return std::get<0>(_M_t); } + /// Return a reference to the stored deleter. deleter_type& get_deleter() noexcept { return std::get<1>(_M_t); } + /// Return a reference to the stored deleter. const deleter_type& get_deleter() const noexcept { return std::get<1>(_M_t); } + /// Return @c true if the stored pointer is not null. explicit operator bool() const noexcept { return get() == pointer() ? false : true; } // Modifiers. + + /// Release ownership of any stored pointer. pointer release() noexcept { @@ -436,12 +564,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __p; } + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ void - reset() noexcept - { reset(pointer()); } - - void - reset(pointer __p) noexcept + reset(pointer __p = pointer()) noexcept { using std::swap; swap(std::get<0>(_M_t), __p); @@ -449,10 +579,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION get_deleter()(__p); } + // Disable resetting from convertible pointer types. template<typename _Up, typename = _Require<is_pointer<pointer>, is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> void reset(_Up*) = delete; + /// Exchange the pointer and deleter with another object. void swap(unique_ptr& __u) noexcept { @@ -471,6 +603,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type) = delete; + // Disable construction from convertible pointer types. template<typename _Up, typename = _Require<is_pointer<pointer>, is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> unique_ptr(_Up*, typename @@ -607,6 +740,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; +#if __cplusplus > 201103L + template<typename _Tp> + struct _MakeUniq + { typedef unique_ptr<_Tp> __single_object; }; + + template<typename _Tp> + struct _MakeUniq<_Tp[]> + { typedef unique_ptr<_Tp[]> __array; }; + + template<typename _Tp, size_t _Bound> + struct _MakeUniq<_Tp[_Bound]> + { struct __invalid_type { }; }; + + /// std::make_unique for single objects + template<typename _Tp, typename... _Args> + inline typename _MakeUniq<_Tp>::__single_object + make_unique(_Args&&... __args) + { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } + + /// std::make_unique for arrays of unknown bound + template<typename _Tp> + inline typename _MakeUniq<_Tp>::__array + make_unique(size_t __num) + { return unique_ptr<_Tp>(new typename remove_extent<_Tp>::type[__num]()); } + + /// Disable std::make_unique for arrays of known bound + template<typename _Tp, typename... _Args> + inline typename _MakeUniq<_Tp>::__invalid_type + make_unique(_Args&&...) = delete; +#endif + // @} group pointer_abstractions _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index be213e04a79..6d5b29e09d2 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -75,12 +75,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * @ingroup unordered_associative_containers * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator<std::pair<const _Key, _Tp>>. * * Meets the requirements of a <a href="tables.html#65">container</a>, and * <a href="tables.html#xx">unordered associative container</a> @@ -113,10 +114,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER //@{ /// Iterator-related typedefs. - typedef typename allocator_type::pointer pointer; - typedef typename allocator_type::const_pointer const_pointer; - typedef typename allocator_type::reference reference; - typedef typename allocator_type::const_reference const_reference; + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; typedef typename _Hashtable::iterator iterator; typedef typename _Hashtable::const_iterator const_iterator; typedef typename _Hashtable::local_iterator local_iterator; @@ -171,6 +172,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER unordered_map(unordered_map&&) = default; /** + * @brief Creates an %unordered_map with no elements. + * @param __a An allocator object. + */ + explicit + unordered_map(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_map to copy. + * @param __a An allocator object. + */ + unordered_map(const unordered_map& __umap, + const allocator_type& __a) + : _M_h(__umap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_map to move. + * @param __a An allocator object. + */ + unordered_map(unordered_map&& __umap, + const allocator_type& __a) + : _M_h(std::move(__umap._M_h), __a) + { } + + /** * @brief Builds an %unordered_map from an initializer_list. * @param __l An initializer_list. * @param __n Minimal initial number of buckets. @@ -367,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Pair&&>::value>::type> std::pair<iterator, bool> insert(_Pair&& __x) - { return _M_h.insert(std::move(__x)); } + { return _M_h.insert(std::forward<_Pair>(__x)); } //@} //@{ @@ -401,7 +431,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Pair&&>::value>::type> iterator insert(const_iterator __hint, _Pair&& __x) - { return _M_h.insert(__hint, std::move(__x)); } + { return _M_h.insert(__hint, std::forward<_Pair>(__x)); } //@} /** @@ -508,6 +538,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void swap(unordered_map& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } // observers. @@ -756,12 +787,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * @ingroup unordered_associative_containers * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator<std::pair<const _Key, _Tp>>. * * Meets the requirements of a <a href="tables.html#65">container</a>, and * <a href="tables.html#xx">unordered associative container</a> @@ -794,10 +826,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER //@{ /// Iterator-related typedefs. - typedef typename allocator_type::pointer pointer; - typedef typename allocator_type::const_pointer const_pointer; - typedef typename allocator_type::reference reference; - typedef typename allocator_type::const_reference const_reference; + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; typedef typename _Hashtable::iterator iterator; typedef typename _Hashtable::const_iterator const_iterator; typedef typename _Hashtable::local_iterator local_iterator; @@ -852,6 +884,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER unordered_multimap(unordered_multimap&&) = default; /** + * @brief Creates an %unordered_multimap with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multimap(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multimap to copy. + * @param __a An allocator object. + */ + unordered_multimap(const unordered_multimap& __ummap, + const allocator_type& __a) + : _M_h(__ummap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_multimap to move. + * @param __a An allocator object. + */ + unordered_multimap(unordered_multimap&& __ummap, + const allocator_type& __a) + : _M_h(std::move(__ummap._M_h), __a) + { } + + /** * @brief Builds an %unordered_multimap from an initializer_list. * @param __l An initializer_list. * @param __n Minimal initial number of buckets. @@ -1032,7 +1093,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Pair&&>::value>::type> iterator insert(_Pair&& __x) - { return _M_h.insert(std::move(__x)); } + { return _M_h.insert(std::forward<_Pair>(__x)); } //@} //@{ @@ -1064,7 +1125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Pair&&>::value>::type> iterator insert(const_iterator __hint, _Pair&& __x) - { return _M_h.insert(__hint, std::move(__x)); } + { return _M_h.insert(__hint, std::forward<_Pair>(__x)); } //@} /** @@ -1173,6 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void swap(unordered_multimap& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } // observers. diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index 50c233d0595..89deb496f11 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -108,10 +108,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER //@{ /// Iterator-related typedefs. - typedef typename allocator_type::pointer pointer; - typedef typename allocator_type::const_pointer const_pointer; - typedef typename allocator_type::reference reference; - typedef typename allocator_type::const_reference const_reference; + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; typedef typename _Hashtable::iterator iterator; typedef typename _Hashtable::const_iterator const_iterator; typedef typename _Hashtable::local_iterator local_iterator; @@ -165,6 +165,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER unordered_set(unordered_set&&) = default; /** + * @brief Creates an %unordered_set with no elements. + * @param __a An allocator object. + */ + explicit + unordered_set(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_set to copy. + * @param __a An allocator object. + */ + unordered_set(const unordered_set& __uset, + const allocator_type& __a) + : _M_h(__uset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_set to move. + * @param __a An allocator object. + */ + unordered_set(unordered_set&& __uset, + const allocator_type& __a) + : _M_h(std::move(__uset._M_h), __a) + { } + + /** * @brief Builds an %unordered_set from an initializer_list. * @param __l An initializer_list. * @param __n Minimal initial number of buckets. @@ -482,6 +511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void swap(unordered_set& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } // observers. @@ -713,10 +743,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER //@{ /// Iterator-related typedefs. - typedef typename allocator_type::pointer pointer; - typedef typename allocator_type::const_pointer const_pointer; - typedef typename allocator_type::reference reference; - typedef typename allocator_type::const_reference const_reference; + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; typedef typename _Hashtable::iterator iterator; typedef typename _Hashtable::const_iterator const_iterator; typedef typename _Hashtable::local_iterator local_iterator; @@ -794,7 +824,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Move assignment operator. unordered_multiset& - operator=(unordered_multiset&& __x) = default; + operator=(unordered_multiset&&) = default; + + /** + * @brief Creates an %unordered_multiset with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multiset(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multiset to copy. + * @param __a An allocator object. + */ + unordered_multiset(const unordered_multiset& __umset, + const allocator_type& __a) + : _M_h(__umset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __umset Input %unordered_multiset to move. + * @param __a An allocator object. + */ + unordered_multiset(unordered_multiset&& __umset, + const allocator_type& __a) + : _M_h(std::move(__umset._M_h), __a) + { } /** * @brief %Unordered_multiset list assignment operator. @@ -1070,6 +1129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void swap(unordered_multiset& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } // observers. diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 0882fe6884a..d26cfafd1fa 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -132,7 +132,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> typename vector<_Tp, _Alloc>::iterator vector<_Tp, _Alloc>:: - erase(iterator __position) + _M_erase(iterator __position) { if (__position + 1 != end()) _GLIBCXX_MOVE3(__position + 1, end(), __position); @@ -144,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> typename vector<_Tp, _Alloc>::iterator vector<_Tp, _Alloc>:: - erase(iterator __first, iterator __last) + _M_erase(iterator __first, iterator __last) { if (__first != __last) { @@ -790,6 +790,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + template<typename _Alloc> + typename vector<bool, _Alloc>::iterator + vector<bool, _Alloc>:: + _M_erase(iterator __position) + { + if (__position + 1 != end()) + std::copy(__position + 1, end(), __position); + --this->_M_impl._M_finish; + return __position; + } + + template<typename _Alloc> + typename vector<bool, _Alloc>::iterator + vector<bool, _Alloc>:: + _M_erase(iterator __first, iterator __last) + { + if (__first != __last) + _M_erase_at_end(std::copy(__last, end(), __first)); + return __first; + } + #if __cplusplus >= 201103L template<typename _Alloc> bool |