summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-26 18:39:06 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-26 18:39:06 +0000
commit21543d4cd558cada630271a0cf3075ad7ce94cbf (patch)
tree08bdb3f3e0a9d0f71e72bb56d9ddb7b916e7dfeb /libstdc++-v3/include/bits
parented0bc1ffb674fe93d0df68654b5bb76869f0bc8c (diff)
downloadgcc-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')
-rw-r--r--libstdc++-v3/include/bits/alloc_traits.h2
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h88
-rw-r--r--libstdc++-v3/include/bits/basic_string.h48
-rw-r--r--libstdc++-v3/include/bits/c++14_warning.h37
-rw-r--r--libstdc++-v3/include/bits/c++config6
-rw-r--r--libstdc++-v3/include/bits/char_traits.h6
-rw-r--r--libstdc++-v3/include/bits/cpp_type_traits.h8
-rw-r--r--libstdc++-v3/include/bits/deque.tcc8
-rw-r--r--libstdc++-v3/include/bits/forward_list.h36
-rw-r--r--libstdc++-v3/include/bits/hashtable.h574
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h217
-rw-r--r--libstdc++-v3/include/bits/list.tcc8
-rw-r--r--libstdc++-v3/include/bits/move.h2
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h417
-rw-r--r--libstdc++-v3/include/bits/random.h3
-rw-r--r--libstdc++-v3/include/bits/random.tcc10
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h4
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h130
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h134
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h172
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h33
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h26
-rw-r--r--libstdc++-v3/include/bits/stl_heap.h14
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h15
-rw-r--r--libstdc++-v3/include/bits/stl_list.h20
-rw-r--r--libstdc++-v3/include/bits/stl_map.h3
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h1
-rw-r--r--libstdc++-v3/include/bits/stl_multiset.h2
-rw-r--r--libstdc++-v3/include/bits/stl_set.h2
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h37
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h26
-rw-r--r--libstdc++-v3/include/bits/unique_ptr.h184
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h110
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h78
-rw-r--r--libstdc++-v3/include/bits/vector.tcc25
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 &apos;\n&apos; 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