diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
commit | 34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch) | |
tree | d503eaf41d085669d1481bb46ec038bc866fece6 /libstdc++-v3/include/bits | |
parent | f733cf303bcdc952c92b81dd62199a40a1f555ec (diff) | |
download | gcc-tarball-34efdaf078b01a7387007c4e6bde6db86384c4b7.tar.gz |
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'libstdc++-v3/include/bits')
119 files changed, 8708 insertions, 2716 deletions
diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index cd98fe0594..3ff4ff7123 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -1,6 +1,6 @@ // <algorithm> Forward declarations -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -45,13 +45,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /* adjacent_find - all_of (C++0x) - any_of (C++0x) + all_of (C++11) + any_of (C++11) binary_search + clamp (C++17) copy copy_backward - copy_if (C++0x) - copy_n (C++0x) + copy_if (C++11) + copy_n (C++11) count count_if equal @@ -62,17 +63,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION find_end find_first_of find_if - find_if_not (C++0x) + find_if_not (C++11) for_each generate generate_n includes inplace_merge - is_heap (C++0x) - is_heap_until (C++0x) - is_partitioned (C++0x) - is_sorted (C++0x) - is_sorted_until (C++0x) + is_heap (C++11) + is_heap_until (C++11) + is_partitioned (C++11) + is_sorted (C++11) + is_sorted_until (C++11) iter_swap lexicographical_compare lower_bound @@ -82,17 +83,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION merge min min_element - minmax (C++0x) - minmax_element (C++0x) + minmax (C++11) + minmax_element (C++11) mismatch next_permutation - none_of (C++0x) + none_of (C++11) nth_element partial_sort partial_sort_copy partition - partition_copy (C++0x) - partition_point (C++0x) + partition_copy (C++11) + partition_point (C++11) pop_heap prev_permutation push_heap @@ -115,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION set_intersection set_symmetric_difference set_union - shuffle (C++0x) + shuffle (C++11) sort sort_heap stable_partition @@ -167,12 +168,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * These algorithms are variations of a classic binary search, and * all assume that the sequence being searched is already sorted. - * + * * The number of comparisons will be logarithmic (and as few as * possible). The number of steps through the sequence will be * logarithmic for random-access iterators (e.g., pointers), and * linear otherwise. - * + * * The LWG has passed Defect Report 270, which notes: <em>The * proposed resolution reinterprets binary search. Instead of * thinking about searching for a value in a sorted range, we view @@ -201,15 +202,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _FIter, typename _Tp> - bool + bool binary_search(_FIter, _FIter, const _Tp&); template<typename _FIter, typename _Tp, typename _Compare> - bool + bool binary_search(_FIter, _FIter, const _Tp&, _Compare); +#if __cplusplus > 201402L + template<typename _Tp> + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&); + + template<typename _Tp, typename _Compare> + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&, _Compare); +#endif + template<typename _IIter, typename _OIter> - _OIter + _OIter copy(_IIter, _IIter, _OIter); template<typename _BIter1, typename _BIter2> @@ -238,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION equal_range(_FIter, _FIter, const _Tp&, _Compare); template<typename _FIter, typename _Tp> - void + void fill(_FIter, _FIter, const _Tp&); template<typename _OIter, typename _Size, typename _Tp> @@ -269,36 +282,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // generate_n template<typename _IIter1, typename _IIter2> - bool + bool includes(_IIter1, _IIter1, _IIter2, _IIter2); template<typename _IIter1, typename _IIter2, typename _Compare> - bool + bool includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); template<typename _BIter> - void + void inplace_merge(_BIter, _BIter, _BIter); template<typename _BIter, typename _Compare> - void + void inplace_merge(_BIter, _BIter, _BIter, _Compare); #if __cplusplus >= 201103L template<typename _RAIter> - bool + bool is_heap(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - bool + bool is_heap(_RAIter, _RAIter, _Compare); template<typename _RAIter> - _RAIter + _RAIter is_heap_until(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - _RAIter + _RAIter is_heap_until(_RAIter, _RAIter, _Compare); template<typename _IIter, typename _Predicate> @@ -315,63 +328,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate); template<typename _FIter> - bool + bool is_sorted(_FIter, _FIter); template<typename _FIter, typename _Compare> - bool + bool is_sorted(_FIter, _FIter, _Compare); template<typename _FIter> - _FIter + _FIter is_sorted_until(_FIter, _FIter); template<typename _FIter, typename _Compare> - _FIter + _FIter is_sorted_until(_FIter, _FIter, _Compare); #endif template<typename _FIter1, typename _FIter2> - void + void iter_swap(_FIter1, _FIter2); template<typename _FIter, typename _Tp> - _FIter + _FIter lower_bound(_FIter, _FIter, const _Tp&); template<typename _FIter, typename _Tp, typename _Compare> - _FIter + _FIter lower_bound(_FIter, _FIter, const _Tp&, _Compare); template<typename _RAIter> - void + void make_heap(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void make_heap(_RAIter, _RAIter, _Compare); - template<typename _Tp> + template<typename _Tp> _GLIBCXX14_CONSTEXPR - const _Tp& + const _Tp& max(const _Tp&, const _Tp&); template<typename _Tp, typename _Compare> _GLIBCXX14_CONSTEXPR - const _Tp& + const _Tp& max(const _Tp&, const _Tp&, _Compare); // max_element // merge - template<typename _Tp> + template<typename _Tp> _GLIBCXX14_CONSTEXPR - const _Tp& + const _Tp& min(const _Tp&, const _Tp&); template<typename _Tp, typename _Compare> _GLIBCXX14_CONSTEXPR - const _Tp& + const _Tp& min(const _Tp&, const _Tp&, _Compare); // min_element @@ -379,7 +392,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Tp> _GLIBCXX14_CONSTEXPR - pair<const _Tp&, const _Tp&> + pair<const _Tp&, const _Tp&> minmax(const _Tp&, const _Tp&); template<typename _Tp, typename _Compare> @@ -431,11 +444,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // mismatch template<typename _BIter> - bool + bool next_permutation(_BIter, _BIter); template<typename _BIter, typename _Compare> - bool + bool next_permutation(_BIter, _BIter, _Compare); #if __cplusplus >= 201103L @@ -469,65 +482,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _RAIter> - void + void pop_heap(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void pop_heap(_RAIter, _RAIter, _Compare); template<typename _BIter> - bool + bool prev_permutation(_BIter, _BIter); template<typename _BIter, typename _Compare> - bool + bool prev_permutation(_BIter, _BIter, _Compare); template<typename _RAIter> - void + void push_heap(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void push_heap(_RAIter, _RAIter, _Compare); // random_shuffle template<typename _FIter, typename _Tp> - _FIter + _FIter remove(_FIter, _FIter, const _Tp&); template<typename _FIter, typename _Predicate> - _FIter + _FIter remove_if(_FIter, _FIter, _Predicate); template<typename _IIter, typename _OIter, typename _Tp> - _OIter + _OIter remove_copy(_IIter, _IIter, _OIter, const _Tp&); template<typename _IIter, typename _OIter, typename _Predicate> - _OIter + _OIter remove_copy_if(_IIter, _IIter, _OIter, _Predicate); // replace template<typename _IIter, typename _OIter, typename _Tp> - _OIter + _OIter replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp> - _OIter + _OIter replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); // replace_if template<typename _BIter> - void + void reverse(_BIter, _BIter); template<typename _BIter, typename _OIter> - _OIter + _OIter reverse_copy(_BIter, _BIter, _OIter); inline namespace _V2 @@ -538,7 +551,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _FIter, typename _OIter> - _OIter + _OIter rotate_copy(_FIter, _FIter, _FIter, _OIter); // search @@ -555,15 +568,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _RAIter> - void + void sort_heap(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void sort_heap(_RAIter, _RAIter, _Compare); template<typename _BIter, typename _Predicate> - _BIter + _BIter stable_partition(_BIter, _BIter, _Predicate); #if __cplusplus < 201103L @@ -579,27 +592,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _FIter1, typename _FIter2> - _FIter2 + _FIter2 swap_ranges(_FIter1, _FIter1, _FIter2); // transform template<typename _FIter> - _FIter + _FIter unique(_FIter, _FIter); template<typename _FIter, typename _BinaryPredicate> - _FIter + _FIter unique(_FIter, _FIter, _BinaryPredicate); // unique_copy template<typename _FIter, typename _Tp> - _FIter + _FIter upper_bound(_FIter, _FIter, const _Tp&); template<typename _FIter, typename _Tp, typename _Compare> - _FIter + _FIter upper_bound(_FIter, _FIter, const _Tp&, _Compare); _GLIBCXX_END_NAMESPACE_VERSION @@ -607,11 +620,11 @@ _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_ALGO template<typename _FIter> - _FIter + _FIter adjacent_find(_FIter, _FIter); template<typename _FIter, typename _BinaryPredicate> - _FIter + _FIter adjacent_find(_FIter, _FIter, _BinaryPredicate); template<typename _IIter, typename _Tp> @@ -623,15 +636,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO count_if(_IIter, _IIter, _Predicate); template<typename _IIter1, typename _IIter2> - bool + bool equal(_IIter1, _IIter1, _IIter2); template<typename _IIter1, typename _IIter2, typename _BinaryPredicate> - bool + bool equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); template<typename _IIter, typename _Tp> - _IIter + _IIter find(_IIter, _IIter, const _Tp&); template<typename _FIter1, typename _FIter2> @@ -647,11 +660,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO find_if(_IIter, _IIter, _Predicate); template<typename _IIter, typename _Funct> - _Funct + _Funct for_each(_IIter, _IIter, _Funct); template<typename _FIter, typename _Generator> - void + void generate(_FIter, _FIter, _Generator); template<typename _OIter, typename _Size, typename _Generator> @@ -659,40 +672,40 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO generate_n(_OIter, _Size, _Generator); template<typename _IIter1, typename _IIter2> - bool + bool lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2); template<typename _IIter1, typename _IIter2, typename _Compare> - bool + bool lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); template<typename _FIter> _GLIBCXX14_CONSTEXPR - _FIter + _FIter max_element(_FIter, _FIter); template<typename _FIter, typename _Compare> _GLIBCXX14_CONSTEXPR - _FIter + _FIter max_element(_FIter, _FIter, _Compare); template<typename _IIter1, typename _IIter2, typename _OIter> - _OIter + _OIter merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - template<typename _IIter1, typename _IIter2, typename _OIter, + template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare> - _OIter + _OIter merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _FIter> _GLIBCXX14_CONSTEXPR - _FIter + _FIter min_element(_FIter, _FIter); template<typename _FIter, typename _Compare> _GLIBCXX14_CONSTEXPR - _FIter + _FIter min_element(_FIter, _FIter, _Compare); template<typename _IIter1, typename _IIter2> @@ -704,31 +717,31 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate); template<typename _RAIter> - void + void nth_element(_RAIter, _RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void nth_element(_RAIter, _RAIter, _RAIter, _Compare); template<typename _RAIter> - void + void partial_sort(_RAIter, _RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void partial_sort(_RAIter, _RAIter, _RAIter, _Compare); template<typename _BIter, typename _Predicate> - _BIter + _BIter partition(_BIter, _BIter, _Predicate); template<typename _RAIter> - void + void random_shuffle(_RAIter, _RAIter); template<typename _RAIter, typename _Generator> - void + void random_shuffle(_RAIter, _RAIter, #if __cplusplus >= 201103L _Generator&&); @@ -737,98 +750,98 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO #endif template<typename _FIter, typename _Tp> - void + void replace(_FIter, _FIter, const _Tp&, const _Tp&); template<typename _FIter, typename _Predicate, typename _Tp> - void + void replace_if(_FIter, _FIter, _Predicate, const _Tp&); template<typename _FIter1, typename _FIter2> - _FIter1 + _FIter1 search(_FIter1, _FIter1, _FIter2, _FIter2); template<typename _FIter1, typename _FIter2, typename _BinaryPredicate> - _FIter1 + _FIter1 search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); template<typename _FIter, typename _Size, typename _Tp> - _FIter + _FIter search_n(_FIter, _FIter, _Size, const _Tp&); - template<typename _FIter, typename _Size, typename _Tp, + template<typename _FIter, typename _Size, typename _Tp, typename _BinaryPredicate> - _FIter + _FIter search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate); template<typename _IIter1, typename _IIter2, typename _OIter> - _OIter + _OIter set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - template<typename _IIter1, typename _IIter2, typename _OIter, + template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare> - _OIter + _OIter set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _IIter1, typename _IIter2, typename _OIter> - _OIter + _OIter set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare> - _OIter + _OIter set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _IIter1, typename _IIter2, typename _OIter> _OIter set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - template<typename _IIter1, typename _IIter2, typename _OIter, + template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare> _OIter - set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _IIter1, typename _IIter2, typename _OIter> - _OIter + _OIter set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare> - _OIter + _OIter set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _RAIter> - void + void sort(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void sort(_RAIter, _RAIter, _Compare); template<typename _RAIter> - void + void stable_sort(_RAIter, _RAIter); template<typename _RAIter, typename _Compare> - void + void stable_sort(_RAIter, _RAIter, _Compare); template<typename _IIter, typename _OIter, typename _UnaryOperation> - _OIter + _OIter transform(_IIter, _IIter, _OIter, _UnaryOperation); - template<typename _IIter1, typename _IIter2, typename _OIter, + template<typename _IIter1, typename _IIter2, typename _OIter, typename _BinaryOperation> - _OIter + _OIter transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation); template<typename _IIter, typename _OIter> - _OIter + _OIter unique_copy(_IIter, _IIter, _OIter); template<typename _IIter, typename _OIter, typename _BinaryPredicate> - _OIter + _OIter unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate); _GLIBCXX_END_NAMESPACE_ALGO diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index d2d13c692a..4d1e489b0c 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -1,6 +1,6 @@ // Allocator traits -*- C++ -*- -// Copyright (C) 2011-2016 Free Software Foundation, Inc. +// Copyright (C) 2011-2017 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 @@ -44,8 +44,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __allocator_traits_base { - template<typename _Alloc, typename _Up> - using __rebind = typename _Alloc::template rebind<_Up>::other; + template<typename _Tp, typename _Up, typename = void> + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template<typename _Tp, typename _Up> + struct __rebind<_Tp, _Up, + __void_t<typename _Tp::template rebind<_Up>::other>> + { using type = typename _Tp::template rebind<_Up>::other; }; protected: template<typename _Tp> @@ -57,10 +62,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __cv_pointer = typename _Tp::const_void_pointer; template<typename _Tp> - using __diff_type = typename _Tp::difference_type; - template<typename _Tp> - using __size_type = typename _Tp::size_type; - template<typename _Tp> using __pocca = typename _Tp::propagate_on_container_copy_assignment; template<typename _Tp> using __pocma = typename _Tp::propagate_on_container_move_assignment; @@ -71,9 +72,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template<typename _Alloc, typename _Up> - using __alloc_rebind = __detected_or_t_<__replace_first_arg_t, - __allocator_traits_base::__rebind, - _Alloc, _Up>; + using __alloc_rebind + = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; /** * @brief Uniform interface to all allocator types. @@ -94,15 +94,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ using pointer = __detected_or_t<value_type*, __pointer, _Alloc>; + private: + // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp> + template<template<typename> class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits<pointer>::template rebind<_Tp>; + }; + + template<template<typename> class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> + { + using type = _Func<_Alloc>; + }; + + // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type + template<typename _A2, typename _PtrT, typename = void> + struct _Diff + { using type = typename pointer_traits<_PtrT>::difference_type; }; + + template<typename _A2, typename _PtrT> + struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>> + { using type = typename _A2::difference_type; }; + + // Select _A2::size_type or make_unsigned<_DiffT>::type + template<typename _A2, typename _DiffT, typename = void> + struct _Size : make_unsigned<_DiffT> { }; + + template<typename _A2, typename _DiffT> + struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>> + { using type = typename _A2::size_type; }; + + public: /** * @brief The allocator's const pointer type. * * @c Alloc::const_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> */ - using const_pointer - = __detected_or_t<__ptr_rebind<pointer, const value_type>, - __c_pointer, _Alloc>; + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; /** * @brief The allocator's void pointer type. @@ -110,8 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::void_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<void> </tt> */ - using void_pointer - = __detected_or_t<__ptr_rebind<pointer, void>, __v_pointer, _Alloc>; + using void_pointer = typename _Ptr<__v_pointer, void>::type; /** * @brief The allocator's const void pointer type. @@ -119,9 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::const_void_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<const void> </tt> */ - using const_void_pointer - = __detected_or_t<__ptr_rebind<pointer, const void>, __cv_pointer, - _Alloc>; + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; /** * @brief The allocator's difference type @@ -129,9 +156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::difference_type if that type exists, otherwise * <tt> pointer_traits<pointer>::difference_type </tt> */ - using difference_type - = __detected_or_t<typename pointer_traits<pointer>::difference_type, - __diff_type, _Alloc>; + using difference_type = typename _Diff<_Alloc, pointer>::type; /** * @brief The allocator's size type @@ -139,9 +164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::size_type if that type exists, otherwise * <tt> make_unsigned<difference_type>::type </tt> */ - using size_type - = __detected_or_t<typename make_unsigned<difference_type>::type, - __size_type, _Alloc>; + using size_type = typename _Size<_Alloc, difference_type>::type; /** * @brief How the allocator is propagated on copy assignment @@ -184,9 +207,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; - static_assert(!is_same<rebind_alloc<value_type>, __undefined>::value, - "allocator defines rebind or is like Alloc<T, Args>"); - private: template<typename _Alloc2> static auto diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h index 2bd9d82fd0..773b3f500f 100644 --- a/libstdc++-v3/include/bits/allocated_ptr.h +++ b/libstdc++-v3/include/bits/allocated_ptr.h @@ -1,6 +1,6 @@ // Guarded Allocation -*- C++ -*- -// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// Copyright (C) 2014-2017 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 @@ -85,10 +85,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION value_type* get() { return _S_raw_ptr(_M_ptr); } private: - value_type* _S_raw_ptr(value_type* __ptr) { return __ptr; } + static value_type* _S_raw_ptr(value_type* __ptr) { return __ptr; } template<typename _Ptr> - auto _S_raw_ptr(_Ptr __ptr) -> decltype(_S_raw_ptr(__ptr.operator->())) + static auto + _S_raw_ptr(_Ptr __ptr) -> decltype(_S_raw_ptr(__ptr.operator->())) { return _S_raw_ptr(__ptr.operator->()); } _Alloc* _M_alloc; diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index 984d80075b..20813864c6 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -1,6 +1,6 @@ // Allocators -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -50,6 +50,9 @@ #endif #define __cpp_lib_incomplete_container_elements 201505 +#if __cplusplus >= 201103L +# define __cpp_lib_allocator_is_always_equal 201411 +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -72,16 +75,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef void value_type; template<typename _Tp1> - struct rebind - { typedef allocator<_Tp1> other; }; + struct rebind + { typedef allocator<_Tp1> other; }; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. std::allocator propagate_on_container_move_assignment typedef true_type propagate_on_container_move_assignment; -#define __cpp_lib_allocator_is_always_equal 201411 typedef true_type is_always_equal; + + template<typename _Up, typename... _Args> + void + construct(_Up* __p, _Args&&... __args) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template<typename _Up> + void + destroy(_Up* __p) { __p->~_Up(); } #endif }; @@ -106,13 +117,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Tp value_type; template<typename _Tp1> - struct rebind - { typedef allocator<_Tp1> other; }; + struct rebind + { typedef allocator<_Tp1> other; }; #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. std::allocator propagate_on_container_move_assignment typedef true_type propagate_on_container_move_assignment; + + typedef true_type is_always_equal; #endif allocator() throw() { } @@ -121,7 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __allocator_base<_Tp>(__a) { } template<typename _Tp1> - allocator(const allocator<_Tp1>&) throw() { } + allocator(const allocator<_Tp1>&) throw() { } ~allocator() throw() { } diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 6bb866bd08..e79ff67ea0 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1,6 +1,6 @@ // -*- C++ -*- header. -// Copyright (C) 2008-2016 Free Software Foundation, Inc. +// Copyright (C) 2008-2017 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 @@ -366,7 +366,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE void store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_acquire); __glibcxx_assert(__b != memory_order_acq_rel); __glibcxx_assert(__b != memory_order_consume); @@ -378,7 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_acquire); __glibcxx_assert(__b != memory_order_acq_rel); __glibcxx_assert(__b != memory_order_consume); @@ -389,7 +389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE __int_type load(memory_order __m = memory_order_seq_cst) const noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_release); __glibcxx_assert(__b != memory_order_acq_rel); @@ -399,7 +399,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE __int_type load(memory_order __m = memory_order_seq_cst) const volatile noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_release); __glibcxx_assert(__b != memory_order_acq_rel); @@ -425,8 +425,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION compare_exchange_weak(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); __glibcxx_assert(__b2 <= __b1); @@ -439,8 +439,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION memory_order __m1, memory_order __m2) volatile noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); __glibcxx_assert(__b2 <= __b1); @@ -468,8 +468,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION compare_exchange_strong(__int_type& __i1, __int_type __i2, memory_order __m1, memory_order __m2) noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); __glibcxx_assert(__b2 <= __b1); @@ -482,8 +482,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION memory_order __m1, memory_order __m2) volatile noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); @@ -695,7 +695,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION store(__pointer_type __p, memory_order __m = memory_order_seq_cst) volatile noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_acquire); __glibcxx_assert(__b != memory_order_acq_rel); __glibcxx_assert(__b != memory_order_consume); @@ -706,7 +706,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE __pointer_type load(memory_order __m = memory_order_seq_cst) const noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_release); __glibcxx_assert(__b != memory_order_acq_rel); @@ -716,7 +716,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE __pointer_type load(memory_order __m = memory_order_seq_cst) const volatile noexcept { - memory_order __b = __m & __memory_order_mask; + memory_order __b = __m & __memory_order_mask; __glibcxx_assert(__b != memory_order_release); __glibcxx_assert(__b != memory_order_acq_rel); @@ -743,8 +743,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION memory_order __m1, memory_order __m2) noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); __glibcxx_assert(__b2 <= __b1); @@ -757,8 +757,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION memory_order __m1, memory_order __m2) volatile noexcept { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; __glibcxx_assert(__b2 != memory_order_release); __glibcxx_assert(__b2 != memory_order_acq_rel); diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h index 2186f7e984..afcfeb7720 100644 --- a/libstdc++-v3/include/bits/atomic_futex.h +++ b/libstdc++-v3/include/bits/atomic_futex.h @@ -1,6 +1,6 @@ // -*- C++ -*- header. -// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// Copyright (C) 2015-2017 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 diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index b4dc372182..318e41b7c5 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -1,6 +1,6 @@ // Iostreams base classes -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index 6c2ea11da1..8b3c829e4b 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -1,6 +1,6 @@ // basic_ios member functions -*- C++ -*- -// Copyright (C) 1999-2016 Free Software Foundation, Inc. +// Copyright (C) 1999-2017 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 @@ -157,17 +157,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc) { if (__builtin_expect(has_facet<__ctype_type>(__loc), true)) - _M_ctype = &use_facet<__ctype_type>(__loc); + _M_ctype = std::__addressof(use_facet<__ctype_type>(__loc)); else _M_ctype = 0; if (__builtin_expect(has_facet<__num_put_type>(__loc), true)) - _M_num_put = &use_facet<__num_put_type>(__loc); + _M_num_put = std::__addressof(use_facet<__num_put_type>(__loc)); else _M_num_put = 0; if (__builtin_expect(has_facet<__num_get_type>(__loc), true)) - _M_num_get = &use_facet<__num_get_type>(__loc); + _M_num_get = std::__addressof(use_facet<__num_get_type>(__loc)); else _M_num_get = 0; } diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 374c985153..b6693c440c 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -1,6 +1,6 @@ // Components for manipulating sequences of characters -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -44,6 +44,11 @@ #include <initializer_list> #endif +#if __cplusplus > 201402L +# include <string_view> +#endif + + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -103,11 +108,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 typedef const_iterator __const_iterator; #endif +#if __cplusplus > 201402L + // A helper type for avoiding boiler-plate. + typedef basic_string_view<_CharT, _Traits> __sv_type; + + template<typename _Tp, typename _Res> + using _If_sv = enable_if_t< + __and_<is_convertible<const _Tp&, __sv_type>, + __not_<is_convertible<const _Tp&, const _CharT*>>>::value, + _Res>; +#endif + // Use empty-base optimization: http://www.cantrip.org/emptyopt.html struct _Alloc_hider : allocator_type // TODO check __is_final { +#if __cplusplus < 201103L _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc()) : allocator_type(__a), _M_p(__dat) { } +#else + _Alloc_hider(pointer __dat, const _Alloc& __a) + : allocator_type(__a), _M_p(__dat) { } + + _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc()) + : allocator_type(std::move(__a)), _M_p(__dat) { } +#endif pointer _M_p; // The actual data. }; @@ -360,7 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } void - _M_assign(const basic_string& __rcs); + _M_assign(const basic_string&); void _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, @@ -399,16 +423,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _Alloc_traits::_S_select_on_copy(__str._M_get_allocator())) { _M_construct(__str._M_data(), __str._M_data() + __str.length()); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2583. no way to supply an allocator for basic_string(str, pos) /** * @brief Construct string as copy of a substring. * @param __str Source string. * @param __pos Index of first character to copy from. - * @param __n Number of characters to copy (default remainder). + * @param __a Allocator to use. + */ + basic_string(const basic_string& __str, size_type __pos, + const _Alloc& __a = _Alloc()) + : _M_dataplus(_M_local_data(), __a) + { + const _CharT* __start = __str._M_data() + + __str._M_check(__pos, "basic_string::basic_string"); + _M_construct(__start, __start + __str._M_limit(__pos, npos)); + } + + /** + * @brief Construct string as copy of a substring. + * @param __str Source string. + * @param __pos Index of first character to copy from. + * @param __n Number of characters to copy. */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2402. [this constructor] shouldn't use Allocator() basic_string(const basic_string& __str, size_type __pos, - size_type __n = npos) + size_type __n) : _M_dataplus(_M_local_data()) { const _CharT* __start = __str._M_data() @@ -420,7 +459,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Construct string as copy of a substring. * @param __str Source string. * @param __pos Index of first character to copy from. - * @param __n Number of characters to copy (default remainder). + * @param __n Number of characters to copy. * @param __a Allocator to use. */ basic_string(const basic_string& __str, size_type __pos, @@ -551,6 +590,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 : _M_dataplus(_M_local_data(), __a) { _M_construct(__beg, __end); } +#if __cplusplus > 201402L + /** + * @brief Construct string from a substring of a string_view. + * @param __t Source string view. + * @param __pos The index of the first character to copy from __t. + * @param __n The number of characters to copy from __t. + * @param __a Allocator to use. + */ + template<typename _Tp, typename = _If_sv<_Tp, void>> + basic_string(const _Tp& __t, size_type __pos, size_type __n, + const _Alloc& __a = _Alloc()) + : basic_string(__sv_type(__t).substr(__pos, __n), __a) { } + + /** + * @brief Construct string from a string_view. + * @param __sv Source string view. + * @param __a Allocator to use (default is default allocator). + */ + explicit + basic_string(__sv_type __sv, const _Alloc& __a = _Alloc()) + : basic_string(__sv.data(), __sv.size(), __a) { } +#endif // C++17 + /** * @brief Destroy the string instance. */ @@ -570,10 +632,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 if (!_Alloc_traits::_S_always_equal() && !_M_is_local() && _M_get_allocator() != __str._M_get_allocator()) { - // replacement allocator cannot free existing storage - _M_destroy(_M_allocated_capacity); - _M_data(_M_local_data()); - _M_set_length(0); + // Propagating allocator cannot free existing storage so must + // deallocate it before replacing current allocator. + if (__str.size() <= _S_local_capacity) + { + _M_destroy(_M_allocated_capacity); + _M_data(_M_local_data()); + _M_set_length(0); + } + else + { + const auto __len = __str.size(); + auto __alloc = __str._M_get_allocator(); + // If this allocation throws there are no effects: + auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1); + _M_destroy(_M_allocated_capacity); + _M_data(__ptr); + _M_capacity(__len); + _M_set_length(__len); + } } std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator()); } @@ -676,6 +753,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Set value to string constructed from a string_view. + * @param __sv A string_view. + */ + template<typename _Tp> + _If_sv<_Tp, basic_string&> + operator=(_Tp __sv) + { return this->assign(__sv); } + + /** + * @brief Convert to a string_view. + * @return A string_view. + */ + operator __sv_type() const noexcept + { return __sv_type(data(), size()); } +#endif // C++17 + // Iterators: /** * Returns a read/write iterator that points to the first character in @@ -1059,6 +1154,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return this->append(__l.begin(), __l.size()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Append a string_view. + * @param __sv The string_view to be appended. + * @return Reference to this string. + */ + basic_string& + operator+=(__sv_type __sv) + { return this->append(__sv); } +#endif // C++17 + /** * @brief Append a string to this string. * @param __str The string to append. @@ -1156,6 +1262,34 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 append(_InputIterator __first, _InputIterator __last) { return this->replace(end(), end(), __first, __last); } +#if __cplusplus > 201402L + /** + * @brief Append a string_view. + * @param __sv The string_view to be appended. + * @return Reference to this string. + */ + basic_string& + append(__sv_type __sv) + { return this->append(__sv.data(), __sv.size()); } + + /** + * @brief Append a range of characters from a string_view. + * @param __sv The string_view to be appended from. + * @param __pos The position in the string_view to append from. + * @param __n The number of characters to append from the string_view. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } +#endif // C++17 + /** * @brief Append a single character. * @param __c Character to append. @@ -1296,6 +1430,34 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return this->assign(__l.begin(), __l.size()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Set value from a string_view. + * @param __sv The source string_view. + * @return Reference to this string. + */ + basic_string& + assign(__sv_type __sv) + { return this->assign(__sv.data(), __sv.size()); } + + /** + * @brief Set value from a range of characters in a string_view. + * @param __sv The source string_view. + * @param __pos The position in the string_view to assign from. + * @param __n The number of characters to assign. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_replace(size_type(0), this->size(), __sv.data() + + __sv._M_check(__pos, "basic_string::assign"), + __sv._M_limit(__pos, __n)); + } +#endif // C++17 + #if __cplusplus >= 201103L /** * @brief Insert multiple characters. @@ -1526,6 +1688,38 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return iterator(_M_data() + __pos); } +#if __cplusplus > 201402L + /** + * @brief Insert a string_view. + * @param __pos Iterator referencing position in string to insert at. + * @param __sv The string_view to insert. + * @return Reference to this string. + */ + basic_string& + insert(size_type __pos, __sv_type __sv) + { return this->insert(__pos, __sv.data(), __sv.size()); } + + /** + * @brief Insert a string_view. + * @param __pos Iterator referencing position in string to insert at. + * @param __sv The string_view to insert from. + * @param __pos Iterator referencing position in string_view to insert + * from. + * @param __n The number of characters to insert. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + size_type __pos2, size_type __n = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, size_type(0), __sv.data() + + __sv._M_check(__pos2, "basic_string::insert"), + __sv._M_limit(__pos2, __n)); + } +#endif // C++17 + /** * @brief Remove characters. * @param __pos Index of first character to remove (default 0). @@ -1544,8 +1738,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_string& erase(size_type __pos = 0, size_type __n = npos) { - this->_M_erase(_M_check(__pos, "basic_string::erase"), - _M_limit(__pos, __n)); + _M_check(__pos, "basic_string::erase"); + if (__n == npos) + this->_M_set_length(__pos); + else if (__n != 0) + this->_M_erase(__pos, _M_limit(__pos, __n)); return *this; } @@ -1582,7 +1779,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last && __last <= end()); const size_type __pos = __first - begin(); - this->_M_erase(__pos, __last - __first); + if (__last == end()) + this->_M_set_length(__pos); + else + this->_M_erase(__pos, __last - __first); return iterator(this->_M_data() + __pos); } @@ -1912,9 +2112,55 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<_CharT> __l) - { return this->replace(__i1, __i2, __l.begin(), __l.end()); } + { return this->replace(__i1, __i2, __l.begin(), __l.size()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Replace range of characters with string_view. + * @param __pos The position to replace at. + * @param __n The number of characters to replace. + * @param __sv The string_view to insert. + * @return Reference to this string. + */ + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) + { return this->replace(__pos, __n, __sv.data(), __sv.size()); } + + /** + * @brief Replace range of characters with string_view. + * @param __pos1 The position to replace at. + * @param __n1 The number of characters to replace. + * @param __sv The string_view to insert from. + * @param __pos2 The position in the string_view to insert from. + * @param __n2 The number of characters to insert. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, __n1, __sv.data() + + __sv._M_check(__pos2, "basic_string::replace"), + __sv._M_limit(__pos2, __n2)); + } + + /** + * @brief Replace range of characters with string_view. + * @param __i1 An iterator referencing the start position + to replace at. + * @param __i2 An iterator referencing the end position + for the replace. + * @param __sv The string_view to insert from. + * @return Reference to this string. + */ + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) + { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } +#endif // C++17 + private: template<class _Integer> basic_string& @@ -1980,13 +2226,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Return const pointer to contents. * - * This is a handle to internal data. Do not modify or dire things may - * happen. + * This is a pointer to internal data. It is undefined to modify + * the contents through the returned pointer. To get a pointer that + * allows modifying the contents use @c &str[0] instead, + * (or in C++17 the non-const @c str.data() overload). */ const _CharT* data() const _GLIBCXX_NOEXCEPT { return _M_data(); } +#if __cplusplus > 201402L + /** + * @brief Return non-const pointer to contents. + * + * This is a pointer to the character sequence held by the string. + * Modifying the characters in the sequence is allowed. + */ + _CharT* + data() noexcept + { return _M_data(); } +#endif + /** * @brief Return copy of allocator used to construct this string. */ @@ -2007,7 +2267,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * npos. */ size_type - find(const _CharT* __s, size_type __pos, size_type __n) const; + find(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find position of a string. @@ -2021,9 +2282,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find position of a string_view. + * @param __sv The string_view to locate. + * @param __pos Index of character to search from (default 0). + * @return Index of start of first occurrence. + */ + size_type + find(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find position of a C string. * @param __s C string to locate. @@ -2035,7 +2308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * it begins. If not found, returns npos. */ size_type - find(const _CharT* __s, size_type __pos = 0) const + find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find(__s, __pos, traits_type::length(__s)); @@ -2066,9 +2339,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type rfind(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->rfind(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find last position of a string_view. + * @param __sv The string_view to locate. + * @param __pos Index of character to search back from (default end). + * @return Index of start of last occurrence. + */ + size_type + rfind(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->rfind(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find last position of a C substring. * @param __s C string to locate. @@ -2082,7 +2367,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * npos. */ size_type - rfind(const _CharT* __s, size_type __pos, size_type __n) const; + rfind(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a C string. @@ -2127,9 +2413,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_of(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_first_of(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find position of a character of a string_view. + * @param __sv A string_view containing characters to locate. + * @param __pos Index of character to search from (default 0). + * @return Index of first occurrence. + */ + size_type + find_first_of(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find_first_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find position of a character of C substring. * @param __s String containing characters to locate. @@ -2143,7 +2441,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns npos. */ size_type - find_first_of(const _CharT* __s, size_type __pos, size_type __n) const; + find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find position of a character of C string. @@ -2157,6 +2456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_of(const _CharT* __s, size_type __pos = 0) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_first_of(__s, __pos, traits_type::length(__s)); @@ -2191,9 +2491,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_of(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_last_of(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find last position of a character of string. + * @param __sv A string_view containing characters to locate. + * @param __pos Index of character to search back from (default end). + * @return Index of last occurrence. + */ + size_type + find_last_of(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->find_last_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find last position of a character of C substring. * @param __s C string containing characters to locate. @@ -2207,7 +2519,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns npos. */ size_type - find_last_of(const _CharT* __s, size_type __pos, size_type __n) const; + find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a character of C string. @@ -2221,6 +2534,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_of(const _CharT* __s, size_type __pos = npos) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_last_of(__s, __pos, traits_type::length(__s)); @@ -2254,9 +2568,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_first_not_of(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find position of a character not in a string_view. + * @param __sv A string_view containing characters to avoid. + * @param __pos Index of character to search from (default 0). + * @return Index of first occurrence. + */ + size_type + find_first_not_of(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find_first_not_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find position of a character not in C substring. * @param __s C string containing characters to avoid. @@ -2271,7 +2597,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_not_of(const _CharT* __s, size_type __pos, - size_type __n) const; + size_type __n) const _GLIBCXX_NOEXCEPT; /** * @brief Find position of a character not in C string. @@ -2285,6 +2611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_first_not_of(__s, __pos, traits_type::length(__s)); @@ -2302,7 +2629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_first_not_of(_CharT __c, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT; + _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a character not in string. @@ -2317,9 +2644,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_last_not_of(__str.data(), __pos, __str.size()); } +#if __cplusplus > 201402L + /** + * @brief Find last position of a character not in a string_view. + * @param __sv A string_view containing characters to avoid. + * @param __pos Index of character to search back from (default end). + * @return Index of last occurrence. + */ + size_type + find_last_not_of(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->find_last_not_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find last position of a character not in C substring. * @param __s C string containing characters to avoid. @@ -2334,7 +2673,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_not_of(const _CharT* __s, size_type __pos, - size_type __n) const; + size_type __n) const _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a character not in C string. * @param __s C string containing characters to avoid. @@ -2348,6 +2687,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_last_not_of(__s, __pos, traits_type::length(__s)); @@ -2365,7 +2705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ size_type find_last_not_of(_CharT __c, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT; + _GLIBCXX_NOEXCEPT; /** * @brief Get a substring. @@ -2411,6 +2751,56 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __r; } +#if __cplusplus > 201402L + /** + * @brief Compare to a string_view. + * @param __sv A string_view to compare against. + * @return Integer < 0, 0, or > 0. + */ + int + compare(__sv_type __sv) const + { + const size_type __size = this->size(); + const size_type __osize = __sv.size(); + const size_type __len = std::min(__size, __osize); + + int __r = traits_type::compare(_M_data(), __sv.data(), __len); + if (!__r) + __r = _S_compare(__size, __osize); + return __r; + } + + /** + * @brief Compare to a string_view. + * @param __pos A position in the string to start comparing from. + * @param __n The number of characters to compare. + * @param __sv A string_view to compare against. + * @return Integer < 0, 0, or > 0. + */ + int + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } + + /** + * @brief Compare to a string_view. + * @param __pos1 A position in the string to start comparing from. + * @param __n1 The number of characters to compare. + * @param __sv A string_view to compare against. + * @param __pos2 A position in the string_view to start comparing from. + * @param __n2 The number of characters to compare. + * @return Integer < 0, 0, or > 0. + */ + template <typename _Tp> + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } +#endif // C++17 + /** * @brief Compare substring to a string. * @param __pos Index of first character of substring. @@ -2475,7 +2865,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * ordered first. */ int - compare(const _CharT* __s) const; + compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 5 String::compare specification questionable @@ -2946,6 +3336,17 @@ _GLIBCXX_END_NAMESPACE_CXX11 _S_empty_rep() _GLIBCXX_NOEXCEPT { return _Rep::_S_empty_rep(); } +#if __cplusplus > 201402L + // A helper type for avoiding boiler-plate. + typedef basic_string_view<_CharT, _Traits> __sv_type; + + template<typename _Tp, typename _Res> + using _If_sv = enable_if_t< + __and_<is_convertible<const _Tp&, __sv_type>, + __not_<is_convertible<const _Tp&, const _CharT*>>>::value, + _Res>; +#endif + public: // Construct/copy/destroy: // NB: We overload ctors in some cases instead of using default @@ -2973,14 +3374,26 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @param __str Source string. */ basic_string(const basic_string& __str); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2583. no way to supply an allocator for basic_string(str, pos) /** * @brief Construct string as copy of a substring. * @param __str Source string. * @param __pos Index of first character to copy from. - * @param __n Number of characters to copy (default remainder). + * @param __a Allocator to use. */ basic_string(const basic_string& __str, size_type __pos, - size_type __n = npos); + const _Alloc& __a = _Alloc()); + + /** + * @brief Construct string as copy of a substring. + * @param __str Source string. + * @param __pos Index of first character to copy from. + * @param __n Number of characters to copy. + */ + basic_string(const basic_string& __str, size_type __pos, + size_type __n); /** * @brief Construct string as copy of a substring. * @param __str Source string. @@ -3055,6 +3468,29 @@ _GLIBCXX_END_NAMESPACE_CXX11 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc()); +#if __cplusplus > 201402L + /** + * @brief Construct string from a substring of a string_view. + * @param __t Source string view. + * @param __pos The index of the first character to copy from __t. + * @param __n The number of characters to copy from __t. + * @param __a Allocator to use. + */ + template<typename _Tp, typename = _If_sv<_Tp, void>> + basic_string(const _Tp& __t, size_type __pos, size_type __n, + const _Alloc& __a = _Alloc()) + : basic_string(__sv_type(__t).substr(__pos, __n), __a) { } + + /** + * @brief Construct string from a string_view. + * @param __sv Source string view. + * @param __a Allocator to use (default is default allocator). + */ + explicit + basic_string(__sv_type __sv, const _Alloc& __a = _Alloc()) + : basic_string(__sv.data(), __sv.size(), __a) { } +#endif // C++17 + /** * @brief Destroy the string instance. */ @@ -3120,6 +3556,24 @@ _GLIBCXX_END_NAMESPACE_CXX11 } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Set value to string constructed from a string_view. + * @param __sv A string_view. + */ + template<typename _Tp> + _If_sv<_Tp, basic_string&> + operator=(_Tp __sv) + { return this->assign(__sv); } + + /** + * @brief Convert to a string_view. + * @return A string_view. + */ + operator __sv_type() const noexcept + { return __sv_type(data(), size()); } +#endif // C++17 + // Iterators: /** * Returns a read/write iterator that points to the first character in @@ -3325,10 +3779,24 @@ _GLIBCXX_END_NAMESPACE_CXX11 /** * Erases the string, making it empty. */ +#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0 + void + clear() _GLIBCXX_NOEXCEPT + { + if (_M_rep()->_M_is_shared()) + { + _M_rep()->_M_dispose(this->get_allocator()); + _M_data(_S_empty_rep()._M_refdata()); + } + else + _M_rep()->_M_set_length_and_sharable(0); + } +#else // PR 56166: this should not throw. void clear() { _M_mutate(0, this->size(), 0); } +#endif /** * Returns true if the %string is empty. Equivalent to @@ -3510,6 +3978,17 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return this->append(__l.begin(), __l.size()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Append a string_view. + * @param __sv The string_view to be appended. + * @return Reference to this string. + */ + basic_string& + operator+=(__sv_type __sv) + { return this->append(__sv); } +#endif // C++17 + /** * @brief Append a string to this string. * @param __str The string to append. @@ -3590,6 +4069,34 @@ _GLIBCXX_END_NAMESPACE_CXX11 append(_InputIterator __first, _InputIterator __last) { return this->replace(_M_iend(), _M_iend(), __first, __last); } +#if __cplusplus > 201402L + /** + * @brief Append a string_view. + * @param __sv The string_view to be appended. + * @return Reference to this string. + */ + basic_string& + append(__sv_type __sv) + { return this->append(__sv.data(), __sv.size()); } + + /** + * @brief Append a range of characters from a string_view. + * @param __sv The string_view to be appended from. + * @param __pos The position in the string_view to append from. + * @param __n The number of characters to append from the string_view. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } +#endif // C++17 + /** * @brief Append a single character. * @param __c Character to append. @@ -3715,6 +4222,34 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return this->assign(__l.begin(), __l.size()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Set value from a string_view. + * @param __sv The source string_view. + * @return Reference to this string. + */ + basic_string& + assign(__sv_type __sv) + { return this->assign(__sv.data(), __sv.size()); } + + /** + * @brief Set value from a range of characters in a string_view. + * @param __sv The source string_view. + * @param __pos The position in the string_view to assign from. + * @param __n The number of characters to assign. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return assign(__sv.data() + + __sv._M_check(__pos, "basic_string::assign"), + __sv._M_limit(__pos, __n)); + } +#endif // C++17 + /** * @brief Insert multiple characters. * @param __p Iterator referencing location in string to insert at. @@ -3890,6 +4425,38 @@ _GLIBCXX_END_NAMESPACE_CXX11 return iterator(_M_data() + __pos); } +#if __cplusplus > 201402L + /** + * @brief Insert a string_view. + * @param __pos Iterator referencing position in string to insert at. + * @param __sv The string_view to insert. + * @return Reference to this string. + */ + basic_string& + insert(size_type __pos, __sv_type __sv) + { return this->insert(__pos, __sv.data(), __sv.size()); } + + /** + * @brief Insert a string_view. + * @param __pos Iterator referencing position in string to insert at. + * @param __sv The string_view to insert from. + * @param __pos Iterator referencing position in string_view to insert + * from. + * @param __n The number of characters to insert. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + size_type __pos2, size_type __n = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, size_type(0), __sv.data() + + __sv._M_check(__pos2, "basic_string::insert"), + __sv._M_limit(__pos2, __n)); + } +#endif // C++17 + /** * @brief Remove characters. * @param __pos Index of first character to remove (default 0). @@ -4244,6 +4811,52 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return this->replace(__i1, __i2, __l.begin(), __l.end()); } #endif // C++11 +#if __cplusplus > 201402L + /** + * @brief Replace range of characters with string_view. + * @param __pos The position to replace at. + * @param __n The number of characters to replace. + * @param __sv The string_view to insert. + * @return Reference to this string. + */ + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) + { return this->replace(__pos, __n, __sv.data(), __sv.size()); } + + /** + * @brief Replace range of characters with string_view. + * @param __pos1 The position to replace at. + * @param __n1 The number of characters to replace. + * @param __sv The string_view to insert from. + * @param __pos2 The position in the string_view to insert from. + * @param __n2 The number of characters to insert. + * @return Reference to this string. + */ + template <typename _Tp> + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, __n1, __sv.data() + + __sv._M_check(__pos2, "basic_string::replace"), + __sv._M_limit(__pos2, __n2)); + } + + /** + * @brief Replace range of characters with string_view. + * @param __i1 An iterator referencing the start position + to replace at. + * @param __i2 An iterator referencing the end position + for the replace. + * @param __sv The string_view to insert from. + * @return Reference to this string. + */ + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) + { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } +#endif // C++17 + private: template<class _Integer> basic_string& @@ -4354,13 +4967,27 @@ _GLIBCXX_END_NAMESPACE_CXX11 /** * @brief Return const pointer to contents. * - * This is a handle to internal data. Do not modify or dire things may - * happen. + * This is a pointer to internal data. It is undefined to modify + * the contents through the returned pointer. To get a pointer that + * allows modifying the contents use @c &str[0] instead, + * (or in C++17 the non-const @c str.data() overload). */ const _CharT* data() const _GLIBCXX_NOEXCEPT { return _M_data(); } +#if __cplusplus > 201402L + /** + * @brief Return non-const pointer to contents. + * + * This is a pointer to the character sequence held by the string. + * Modifying the characters in the sequence is allowed. + */ + _CharT* + data() noexcept + { return _M_data(); } +#endif + /** * @brief Return copy of allocator used to construct this string. */ @@ -4381,7 +5008,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 * npos. */ size_type - find(const _CharT* __s, size_type __pos, size_type __n) const; + find(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find position of a string. @@ -4395,7 +5023,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find(__str.data(), __pos, __str.size()); } /** @@ -4409,7 +5037,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * it begins. If not found, returns npos. */ size_type - find(const _CharT* __s, size_type __pos = 0) const + find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find(__s, __pos, traits_type::length(__s)); @@ -4428,6 +5056,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 size_type find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; +#if __cplusplus > 201402L + /** + * @brief Find position of a string_view. + * @param __sv The string_view to locate. + * @param __pos Index of character to search from (default 0). + * @return Index of start of first occurrence. + */ + size_type + find(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find last position of a string. * @param __str String to locate. @@ -4440,7 +5080,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type rfind(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->rfind(__str.data(), __pos, __str.size()); } /** @@ -4456,7 +5096,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 * npos. */ size_type - rfind(const _CharT* __s, size_type __pos, size_type __n) const; + rfind(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a C string. @@ -4469,7 +5110,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * where it begins. If not found, returns npos. */ size_type - rfind(const _CharT* __s, size_type __pos = npos) const + rfind(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->rfind(__s, __pos, traits_type::length(__s)); @@ -4488,6 +5129,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 size_type rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; +#if __cplusplus > 201402L + /** + * @brief Find last position of a string_view. + * @param __sv The string_view to locate. + * @param __pos Index of character to search back from (default end). + * @return Index of start of last occurrence. + */ + size_type + rfind(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->rfind(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find position of a character of string. * @param __str String containing characters to locate. @@ -4501,7 +5154,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_of(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_first_of(__str.data(), __pos, __str.size()); } /** @@ -4517,7 +5170,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 * returns npos. */ size_type - find_first_of(const _CharT* __s, size_type __pos, size_type __n) const; + find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find position of a character of C string. @@ -4531,6 +5185,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_of(const _CharT* __s, size_type __pos = 0) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_first_of(__s, __pos, traits_type::length(__s)); @@ -4552,6 +5207,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { return this->find(__c, __pos); } +#if __cplusplus > 201402L + /** + * @brief Find position of a character of a string_view. + * @param __sv A string_view containing characters to locate. + * @param __pos Index of character to search from (default 0). + * @return Index of first occurrence. + */ + size_type + find_first_of(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find_first_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find last position of a character of string. * @param __str String containing characters to locate. @@ -4565,7 +5232,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_of(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_last_of(__str.data(), __pos, __str.size()); } /** @@ -4581,7 +5248,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 * returns npos. */ size_type - find_last_of(const _CharT* __s, size_type __pos, size_type __n) const; + find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a character of C string. @@ -4595,6 +5263,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_of(const _CharT* __s, size_type __pos = npos) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_last_of(__s, __pos, traits_type::length(__s)); @@ -4616,6 +5285,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT { return this->rfind(__c, __pos); } +#if __cplusplus > 201402L + /** + * @brief Find last position of a character of string. + * @param __sv A string_view containing characters to locate. + * @param __pos Index of character to search back from (default end). + * @return Index of last occurrence. + */ + size_type + find_last_of(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->find_last_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 + /** * @brief Find position of a character not in string. * @param __str String containing characters to avoid. @@ -4628,7 +5309,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_first_not_of(__str.data(), __pos, __str.size()); } /** @@ -4645,7 +5326,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_not_of(const _CharT* __s, size_type __pos, - size_type __n) const; + size_type __n) const _GLIBCXX_NOEXCEPT; /** * @brief Find position of a character not in C string. @@ -4659,6 +5340,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_first_not_of(__s, __pos, traits_type::length(__s)); @@ -4676,7 +5358,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_first_not_of(_CharT __c, size_type __pos = 0) const - _GLIBCXX_NOEXCEPT; + _GLIBCXX_NOEXCEPT; + +#if __cplusplus > 201402L + /** + * @brief Find position of a character not in a string_view. + * @param __sv A string_view containing characters to avoid. + * @param __pos Index of character to search from (default 0). + * @return Index of first occurrence. + */ + size_type + find_first_not_of(__sv_type __sv, size_type __pos = 0) const noexcept + { return this->find_first_not_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 /** * @brief Find last position of a character not in string. @@ -4691,7 +5385,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT + _GLIBCXX_NOEXCEPT { return this->find_last_not_of(__str.data(), __pos, __str.size()); } /** @@ -4708,7 +5402,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_not_of(const _CharT* __s, size_type __pos, - size_type __n) const; + size_type __n) const _GLIBCXX_NOEXCEPT; /** * @brief Find last position of a character not in C string. * @param __s C string containing characters to avoid. @@ -4722,6 +5416,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); return this->find_last_not_of(__s, __pos, traits_type::length(__s)); @@ -4739,7 +5434,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ size_type find_last_not_of(_CharT __c, size_type __pos = npos) const - _GLIBCXX_NOEXCEPT; + _GLIBCXX_NOEXCEPT; + +#if __cplusplus > 201402L + /** + * @brief Find last position of a character not in a string_view. + * @param __sv A string_view containing characters to avoid. + * @param __pos Index of character to search back from (default end). + * @return Index of last occurrence. + */ + size_type + find_last_not_of(__sv_type __sv, size_type __pos = npos) const noexcept + { return this->find_last_not_of(__sv.data(), __pos, __sv.size()); } +#endif // C++17 /** * @brief Get a substring. @@ -4785,6 +5492,56 @@ _GLIBCXX_END_NAMESPACE_CXX11 return __r; } +#if __cplusplus > 201402L + /** + * @brief Compare to a string_view. + * @param __sv A string_view to compare against. + * @return Integer < 0, 0, or > 0. + */ + int + compare(__sv_type __sv) const + { + const size_type __size = this->size(); + const size_type __osize = __sv.size(); + const size_type __len = std::min(__size, __osize); + + int __r = traits_type::compare(_M_data(), __sv.data(), __len); + if (!__r) + __r = _S_compare(__size, __osize); + return __r; + } + + /** + * @brief Compare to a string_view. + * @param __pos A position in the string to start comparing from. + * @param __n The number of characters to compare. + * @param __sv A string_view to compare against. + * @return Integer < 0, 0, or > 0. + */ + int + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } + + /** + * @brief Compare to a string_view. + * @param __pos1 A position in the string to start comparing from. + * @param __n1 The number of characters to compare. + * @param __sv A string_view to compare against. + * @param __pos2 A position in the string_view to start comparing from. + * @param __n2 The number of characters to compare. + * @return Integer < 0, 0, or > 0. + */ + template <typename _Tp> + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } +#endif // C++17 + /** * @brief Compare substring to a string. * @param __pos Index of first character of substring. @@ -4849,7 +5606,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * ordered first. */ int - compare(const _CharT* __s) const; + compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 5 String::compare specification questionable @@ -5698,6 +6455,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; #endif +_GLIBCXX_END_NAMESPACE_VERSION + #if __cplusplus > 201103L #define __cpp_lib_string_udls 201304 @@ -5706,6 +6465,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { inline namespace string_literals { +_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_DEFAULT_ABI_TAG inline basic_string<char> @@ -5731,12 +6491,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return basic_string<char32_t>{__str, __len}; } #endif +_GLIBCXX_END_NAMESPACE_VERSION } // inline namespace string_literals } // inline namespace literals #endif // __cplusplus > 201103L -_GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 2b6644d1c4..41b7fa196b 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -1,6 +1,6 @@ // Components for manipulating sequences of characters -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -351,7 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__size < __n) this->append(__n - __size, __c); else if (__n < __size) - this->_M_erase(__n, __size - __n); + this->_M_set_length(__n); } template<typename _CharT, typename _Traits, typename _Alloc> @@ -621,6 +621,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits, typename _Alloc> basic_string<_CharT, _Traits, _Alloc>:: + basic_string(const basic_string& __str, size_type __pos, const _Alloc& __a) + : _M_dataplus(_S_construct(__str._M_data() + + __str._M_check(__pos, + "basic_string::basic_string"), + __str._M_data() + __str._M_limit(__pos, npos) + + __pos, __a), __a) + { } + + template<typename _CharT, typename _Traits, typename _Alloc> + basic_string<_CharT, _Traits, _Alloc>:: basic_string(const basic_string& __str, size_type __pos, size_type __n) : _M_dataplus(_S_construct(__str._M_data() + __str._M_check(__pos, @@ -1176,21 +1186,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); const size_type __size = this->size(); - const _CharT* __data = _M_data(); if (__n == 0) return __pos <= __size ? __pos : npos; + if (__pos >= __size) + return npos; - if (__n <= __size) + const _CharT __elem0 = __s[0]; + const _CharT* const __data = data(); + const _CharT* __first = __data + __pos; + const _CharT* const __last = __data + __size; + size_type __len = __size - __pos; + + while (__len >= __n) { - for (; __pos <= __size - __n; ++__pos) - if (traits_type::eq(__data[__pos], __s[0]) - && traits_type::compare(__data + __pos + 1, - __s + 1, __n - 1) == 0) - return __pos; + // Find the first occurrence of __elem0: + __first = traits_type::find(__first, __len - __n + 1, __elem0); + if (!__first) + return npos; + // Compare the full strings from the first occurrence of __elem0. + // We already know that __first[0] == __s[0] but compare them again + // anyway because __s is probably aligned, which helps memcmp. + if (traits_type::compare(__first, __s, __n) == 0) + return __first - __data; + __len = __last - ++__first; } return npos; } @@ -1217,6 +1240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: rfind(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); const size_type __size = this->size(); @@ -1255,6 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); for (; __n && __pos < this->size(); ++__pos) @@ -1270,6 +1295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); size_type __size = this->size(); @@ -1291,6 +1317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); for (; __pos < this->size(); ++__pos) @@ -1314,6 +1341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const + _GLIBCXX_NOEXCEPT { __glibcxx_requires_string_len(__s, __n); size_type __size = this->size(); @@ -1387,7 +1415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits, typename _Alloc> int basic_string<_CharT, _Traits, _Alloc>:: - compare(const _CharT* __s) const + compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT { __glibcxx_requires_string(__s); const size_type __size = this->size(); @@ -1569,7 +1597,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. -#if _GLIBCXX_EXTERN_TEMPLATE > 0 +#if _GLIBCXX_EXTERN_TEMPLATE > 0 && __cplusplus <= 201402L extern template class basic_string<char>; extern template basic_istream<char>& diff --git a/libstdc++-v3/include/bits/boost_concept_check.h b/libstdc++-v3/include/bits/boost_concept_check.h index 8429c0f523..fb9a643c86 100644 --- a/libstdc++-v3/include/bits/boost_concept_check.h +++ b/libstdc++-v3/include/bits/boost_concept_check.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2004-2016 Free Software Foundation, Inc. +// Copyright (C) 2004-2017 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 diff --git a/libstdc++-v3/include/bits/c++0x_warning.h b/libstdc++-v3/include/bits/c++0x_warning.h index cec4968861..d2bc7148cc 100644 --- a/libstdc++-v3/include/bits/c++0x_warning.h +++ b/libstdc++-v3/include/bits/c++0x_warning.h @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 diff --git a/libstdc++-v3/include/bits/c++14_warning.h b/libstdc++-v3/include/bits/c++14_warning.h index f3cb99c593..5ead9c6b12 100644 --- a/libstdc++-v3/include/bits/c++14_warning.h +++ b/libstdc++-v3/include/bits/c++14_warning.h @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -29,9 +29,9 @@ #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. +#error This file requires compiler and library support \ +for the ISO C++ 2014 standard. This support must be enabled \ +with the -std=c++14 or -std=gnu++14 compiler options. #endif #endif diff --git a/libstdc++-v3/include/bits/c++17_warning.h b/libstdc++-v3/include/bits/c++17_warning.h new file mode 100644 index 0000000000..759fdc9225 --- /dev/null +++ b/libstdc++-v3/include/bits/c++17_warning.h @@ -0,0 +1,37 @@ +// Copyright (C) 2016-2017 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++17_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _CXX17_WARNING_H +#define _CXX17_WARNING_H 1 + +#if __cplusplus <= 201402L +#error This file requires compiler and library support \ +for the ISO C++ 2017 standard. This support must be enabled \ +with the -std=c++17 or -std=gnu++17 compiler options. +#endif + +#endif diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 4625607425..8ca6b0345b 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -1,6 +1,6 @@ // Predefined symbols and macros -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -30,7 +30,10 @@ #ifndef _GLIBCXX_CXX_CONFIG_H #define _GLIBCXX_CXX_CONFIG_H 1 -// The current version of the C++ library in compressed ISO date format. +// The major release number for the GCC release the C++ library belongs to. +#define _GLIBCXX_RELEASE + +// The datestamp of the C++ library in compressed ISO date format. #define __GLIBCXX__ // Macros for various attributes. @@ -111,6 +114,22 @@ # endif #endif +#ifndef _GLIBCXX17_CONSTEXPR +# if __cplusplus > 201402L +# define _GLIBCXX17_CONSTEXPR constexpr +# else +# define _GLIBCXX17_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_INLINE +# if __cplusplus > 201402L +# define _GLIBCXX17_INLINE inline +# else +# define _GLIBCXX17_INLINE +# endif +#endif + // Macro for noexcept, to support in mixed 03/0x mode. #ifndef _GLIBCXX_NOEXCEPT # if __cplusplus >= 201103L @@ -138,6 +157,14 @@ # endif #endif +#if __cpp_noexcept_function_type +#define _GLIBCXX_NOEXCEPT_PARM , bool _NE +#define _GLIBCXX_NOEXCEPT_QUAL noexcept (_NE) +#else +#define _GLIBCXX_NOEXCEPT_PARM +#define _GLIBCXX_NOEXCEPT_QUAL +#endif + // Macro for extern template, ie controlling template linkage via use // of extern keyword on template declaration. As documented in the g++ // manual, it inhibits all implicit instantiations and is used @@ -160,7 +187,9 @@ namespace __profile { } namespace __cxx1998 { } - namespace __detail { } + namespace __detail { + namespace __variant { } // C++17 + } namespace rel_ops { } @@ -175,12 +204,16 @@ namespace decimal { } - namespace chrono { } - namespace placeholders { } - namespace regex_constants { } - namespace this_thread { } - - namespace experimental { } + namespace chrono { } // C++11 + namespace placeholders { } // C++11 + namespace regex_constants { } // C++11 + namespace this_thread { } // C++11 + inline namespace literals { // C++14 + inline namespace chrono_literals { } // C++14 + inline namespace complex_literals { } // C++14 + inline namespace string_literals { } // C++14 + inline namespace string_view_literals { } // C++17 + } } namespace abi { } @@ -260,14 +293,30 @@ namespace std namespace decimal { inline namespace __7 { } } +#if __cplusplus >= 201103L namespace chrono { inline namespace __7 { } } namespace placeholders { inline namespace __7 { } } namespace regex_constants { inline namespace __7 { } } namespace this_thread { inline namespace __7 { } } - namespace experimental { inline namespace __7 { } } +#if __cplusplus >= 201402L + inline namespace literals { + inline namespace chrono_literals { inline namespace __7 { } } + inline namespace complex_literals { inline namespace __7 { } } + inline namespace string_literals { inline namespace __7 { } } +#if __cplusplus > 201402L + inline namespace string_view_literals { inline namespace __7 { } } +#endif // C++17 + } +#endif // C++14 +#endif // C++11 - namespace __detail { inline namespace __7 { } } + namespace __detail { + inline namespace __7 { } +#if __cplusplus > 201402L + namespace __variant { inline namespace __7 { } } +#endif + } } namespace __gnu_cxx @@ -350,6 +399,10 @@ namespace std namespace _GLIBCXX_STD_C { _GLIBCXX_BEGIN_NAMESPACE_VERSION # define _GLIBCXX_END_NAMESPACE_CONTAINER \ _GLIBCXX_END_NAMESPACE_VERSION } +#else +# define _GLIBCXX_STD_C std +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_VERSION +# define _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_VERSION #endif #ifdef _GLIBCXX_PARALLEL @@ -358,30 +411,10 @@ namespace std namespace _GLIBCXX_STD_A { _GLIBCXX_BEGIN_NAMESPACE_VERSION # define _GLIBCXX_END_NAMESPACE_ALGO \ _GLIBCXX_END_NAMESPACE_VERSION } -#endif - -#ifndef _GLIBCXX_STD_A +#else # define _GLIBCXX_STD_A std -#endif - -#ifndef _GLIBCXX_STD_C -# define _GLIBCXX_STD_C std -#endif - -#ifndef _GLIBCXX_BEGIN_NAMESPACE_ALGO -# define _GLIBCXX_BEGIN_NAMESPACE_ALGO -#endif - -#ifndef _GLIBCXX_END_NAMESPACE_ALGO -# define _GLIBCXX_END_NAMESPACE_ALGO -#endif - -#ifndef _GLIBCXX_BEGIN_NAMESPACE_CONTAINER -# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER -#endif - -#ifndef _GLIBCXX_END_NAMESPACE_CONTAINER -# define _GLIBCXX_END_NAMESPACE_CONTAINER +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO _GLIBCXX_BEGIN_NAMESPACE_VERSION +# define _GLIBCXX_END_NAMESPACE_ALGO _GLIBCXX_END_NAMESPACE_VERSION #endif // GLIBCXX_ABI Deprecated @@ -413,7 +446,7 @@ namespace std #endif // Debug Mode implies checking assertions. -#ifdef _GLIBCXX_DEBUG +#if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS) # define _GLIBCXX_ASSERTIONS 1 #endif @@ -424,9 +457,8 @@ namespace std #endif // Assert. -#if !defined(_GLIBCXX_ASSERTIONS) && !defined(_GLIBCXX_PARALLEL) -# define __glibcxx_assert(_Condition) -#else +#if defined(_GLIBCXX_ASSERTIONS) \ + || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS) namespace std { // Avoid the use of assert, because we're trying to keep the <cassert> @@ -440,7 +472,7 @@ namespace std __builtin_abort(); } } -#define __glibcxx_assert(_Condition) \ +#define __glibcxx_assert_impl(_Condition) \ do \ { \ if (! (_Condition)) \ @@ -449,6 +481,12 @@ namespace std } while (false) #endif +#if defined(_GLIBCXX_ASSERTIONS) +# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition) +#else +# define __glibcxx_assert(_Condition) +#endif + // Macros for race detectors. // _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and // _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain @@ -532,6 +570,13 @@ namespace std #define _GLIBCXX_TXN_SAFE_DYN #endif +#if __cplusplus > 201402L +// In C++17 mathematical special functions are in namespace std. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#elif __cplusplus >= 201103L && __STDCPP_WANT_MATH_SPEC_FUNCS__ != 0 +// For C++11 and C++14 they are in namespace std when requested. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#endif // The remainder of the prewritten config is automatic; all the // user hooks are listed above. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index fd2da76650..75db5b8932 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -1,6 +1,6 @@ // Character Traits for use by standard string and iostream -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -88,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename _Char_types<_CharT>::off_type off_type; typedef typename _Char_types<_CharT>::state_type state_type; - static void + static _GLIBCXX14_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) { __c1 = __c2; } @@ -100,13 +100,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) { return __c1 < __c2; } - static int + static _GLIBCXX14_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, std::size_t __n); - static std::size_t + static _GLIBCXX14_CONSTEXPR std::size_t length(const char_type* __s); - static const char_type* + static _GLIBCXX14_CONSTEXPR const char_type* find(const char_type* __s, std::size_t __n, const char_type& __a); static char_type* @@ -139,8 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } }; +// #define __cpp_lib_constexpr_char_traits 201611 + template<typename _CharT> - int + _GLIBCXX14_CONSTEXPR int char_traits<_CharT>:: compare(const char_type* __s1, const char_type* __s2, std::size_t __n) { @@ -153,7 +155,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _CharT> - std::size_t + _GLIBCXX14_CONSTEXPR std::size_t char_traits<_CharT>:: length(const char_type* __p) { @@ -164,7 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _CharT> - const typename char_traits<_CharT>::char_type* + _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* char_traits<_CharT>:: find(const char_type* __s, std::size_t __n, const char_type& __a) { @@ -238,7 +240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef streamoff off_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { __c1 = __c2; } @@ -254,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION < static_cast<unsigned char>(__c2)); } - static int + static /* _GLIBCXX17_CONSTEXPR */ int compare(const char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) @@ -262,11 +264,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __builtin_memcmp(__s1, __s2, __n); } - static size_t + static /* _GLIBCXX17_CONSTEXPR */ size_t length(const char_type* __s) { return __builtin_strlen(__s); } - static const char_type* + static /* _GLIBCXX17_CONSTEXPR */ const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { if (__n == 0) @@ -333,7 +335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef wstreampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { __c1 = __c2; } @@ -345,7 +347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { return __c1 < __c2; } - static int + static /* _GLIBCXX17_CONSTEXPR */ int compare(const char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) @@ -353,11 +355,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return wmemcmp(__s1, __s2, __n); } - static size_t + static /* _GLIBCXX17_CONSTEXPR */ size_t length(const char_type* __s) { return wcslen(__s); } - static const char_type* + static /* _GLIBCXX17_CONSTEXPR */ const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { if (__n == 0) @@ -432,7 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef u16streampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) noexcept { __c1 = __c2; } @@ -444,7 +446,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) noexcept { return __c1 < __c2; } - static int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (size_t __i = 0; __i < __n; ++__i) @@ -455,7 +457,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - static size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { size_t __i = 0; @@ -464,7 +466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __i; } - static const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { for (size_t __i = 0; __i < __n; ++__i) @@ -529,7 +531,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef u32streampos pos_type; typedef mbstate_t state_type; - static void + static _GLIBCXX17_CONSTEXPR void assign(char_type& __c1, const char_type& __c2) noexcept { __c1 = __c2; } @@ -541,7 +543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) noexcept { return __c1 < __c2; } - static int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (size_t __i = 0; __i < __n; ++__i) @@ -552,7 +554,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - static size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) { size_t __i = 0; @@ -561,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __i; } - static const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { for (size_t __i = 0; __i < __n; ++__i) diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h index 8a335af6cf..fc2da321ab 100644 --- a/libstdc++-v3/include/bits/codecvt.h +++ b/libstdc++-v3/include/bits/codecvt.h @@ -1,6 +1,6 @@ // Locale support (codecvt) -*- C++ -*- -// Copyright (C) 2000-2016 Free Software Foundation, Inc. +// Copyright (C) 2000-2017 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 diff --git a/libstdc++-v3/include/bits/concept_check.h b/libstdc++-v3/include/bits/concept_check.h index 11092c0a78..83a96f4dc9 100644 --- a/libstdc++-v3/include/bits/concept_check.h +++ b/libstdc++-v3/include/bits/concept_check.h @@ -1,6 +1,6 @@ // Concept-checking control -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index fff1e9949d..932360cd2f 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -1,6 +1,6 @@ // The -*- C++ -*- type traits classes for internal use in libstdc++ -// Copyright (C) 2000-2016 Free Software Foundation, Inc. +// Copyright (C) 2000-2017 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 diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index b1dab643f3..38a6e82aae 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -1,6 +1,6 @@ // Deque implementation (out of line) -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -119,7 +119,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const_iterator __mid = __x.begin() + difference_type(__len); std::copy(__x.begin(), __mid, this->_M_impl._M_start); - insert(this->_M_impl._M_finish, __mid, __x.end()); + _M_range_insert_aux(this->_M_impl._M_finish, __mid, __x.end(), + std::random_access_iterator_tag()); } } return *this; @@ -128,7 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _Tp, typename _Alloc> template<typename... _Args> +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else void +#endif deque<_Tp, _Alloc>:: emplace_front(_Args&&... __args) { @@ -141,11 +146,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } else _M_push_front_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif } template<typename _Tp, typename _Alloc> template<typename... _Args> +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else void +#endif deque<_Tp, _Alloc>:: emplace_back(_Args&&... __args) { @@ -159,6 +171,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } else _M_push_back_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif } #endif @@ -280,7 +295,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__first == __last) _M_erase_at_end(__cur); else - insert(end(), __first, __last); + _M_range_insert_aux(end(), __first, __last, + std::__iterator_category(__first)); } template <typename _Tp, typename _Alloc> diff --git a/libstdc++-v3/include/bits/enable_special_members.h b/libstdc++-v3/include/bits/enable_special_members.h index 1ac8f38935..2c35eb50ad 100644 --- a/libstdc++-v3/include/bits/enable_special_members.h +++ b/libstdc++-v3/include/bits/enable_special_members.h @@ -1,6 +1,6 @@ // <bits/enable_special_members.h> -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -36,13 +36,33 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + struct _Enable_default_constructor_tag + { + explicit constexpr _Enable_default_constructor_tag() = default; + }; + /** * @brief A mixin helper to conditionally enable or disable the default * constructor. * @sa _Enable_special_members */ template<bool _Switch, typename _Tag = void> - struct _Enable_default_constructor { }; + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; /** @@ -86,7 +106,21 @@ template<bool _Default, bool _Destructor, template<typename _Tag> struct _Enable_default_constructor<false, _Tag> - { constexpr _Enable_default_constructor() noexcept = delete; }; + { + constexpr _Enable_default_constructor() noexcept = delete; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; template<typename _Tag> struct _Enable_destructor<false, _Tag> diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index 2e8d39f712..c37bf01345 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -1,6 +1,6 @@ // <forward_list.h> -*- C++ -*- -// Copyright (C) 2008-2016 Free Software Foundation, Inc. +// Copyright (C) 2008-2017 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 @@ -566,8 +566,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __list A %forward_list of identical element and allocator * types. * - * All the elements of @a __list are copied, but unlike the copy - * constructor, the allocator object is not copied. + * All the elements of @a __list are copied. + * + * Whether the allocator is copied depends on the allocator traits. */ forward_list& operator=(const forward_list& __list); @@ -579,7 +580,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * The contents of @a __list are moved into this %forward_list * (without copying, if the allocators permit it). - * @a __list is a valid, but unspecified %forward_list + * + * Afterwards @a __list is a valid, but unspecified %forward_list + * + * Whether the allocator is moved depends on the allocator traits. */ forward_list& operator=(forward_list&& __list) @@ -617,7 +621,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %forward_list and * that the number of elements of the resulting %forward_list is the - * same as the number of elements assigned. Old data is lost. + * same as the number of elements assigned. */ template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> @@ -636,7 +640,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function fills a %forward_list with @a __n copies of the * given value. Note that the assignment completely changes the * %forward_list, and that the resulting %forward_list has __n - * elements. Old data is lost. + * elements. */ void assign(size_type __n, const _Tp& __val) @@ -793,10 +797,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and references. */ template<typename... _Args> - void +#if __cplusplus > 201402L + reference +#else + void +#endif emplace_front(_Args&&... __args) - { this->_M_insert_after(cbefore_begin(), - std::forward<_Args>(__args)...); } + { + this->_M_insert_after(cbefore_begin(), + std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } /** * @brief Add data to the front of the %forward_list. @@ -991,6 +1004,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * time. Note that the global std::swap() function is * specialized such that std::swap(l1,l2) will feed to this * function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(forward_list& __list) noexcept diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc index 7cc630f06d..b823b09e1a 100644 --- a/libstdc++-v3/include/bits/forward_list.tcc +++ b/libstdc++-v3/include/bits/forward_list.tcc @@ -1,6 +1,6 @@ // <forward_list.tcc> -*- C++ -*- -// Copyright (C) 2008-2016 Free Software Foundation, Inc. +// Copyright (C) 2008-2017 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 diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index a6e83f7ed9..b1beff86ab 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -1,6 +1,6 @@ // File based streams -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/functexcept.h b/libstdc++-v3/include/bits/functexcept.h index 86ca5caab5..148351f9fa 100644 --- a/libstdc++-v3/include/bits/functexcept.h +++ b/libstdc++-v3/include/bits/functexcept.h @@ -1,6 +1,6 @@ // Function-Based Exception Support -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index def35f589e..38be1724d3 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -1,6 +1,6 @@ // functional_hash.h header -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -57,6 +57,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct hash; + template<typename _Tp, typename = void> + struct __poison_hash + { + static constexpr bool __enable_hash_call = false; + private: + // Private rather than deleted to be non-trivially-copyable. + __poison_hash(__poison_hash&&); + ~__poison_hash(); + }; + + template<typename _Tp> + struct __poison_hash<_Tp, __void_t<decltype(hash<_Tp>()(declval<_Tp>()))>> + { + static constexpr bool __enable_hash_call = true; + }; + // Helper struct for SFINAE-poisoning non-enum types. template<typename _Tp, bool = is_enum<_Tp>::value> struct __hash_enum @@ -186,6 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return hash(&__val, sizeof(__val), __hash); } }; + // A hash function similar to FNV-1a (see PR59406 for how it differs). struct _Fnv_hash_impl { static size_t diff --git a/libstdc++-v3/include/bits/gslice.h b/libstdc++-v3/include/bits/gslice.h index d49adfe0f1..8909dfde03 100644 --- a/libstdc++-v3/include/bits/gslice.h +++ b/libstdc++-v3/include/bits/gslice.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- gslice class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/gslice_array.h b/libstdc++-v3/include/bits/gslice_array.h index 4f4ded0b84..dd4545017d 100644 --- a/libstdc++-v3/include/bits/gslice_array.h +++ b/libstdc++-v3/include/bits/gslice_array.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- gslice_array class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 5748920cc7..bc7448bcf1 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -1,6 +1,6 @@ // hashtable.h header -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -33,6 +33,9 @@ #pragma GCC system_header #include <bits/hashtable_policy.h> +#if __cplusplus > 201402L +# include <bits/node_handle.h> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -294,7 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _ExtractKeya, typename _Equala, typename _H1a, typename _H2a, typename _Hasha, typename _RehashPolicya, typename _Traitsa, - bool _Constant_iteratorsa, bool _Unique_keysa> + bool _Constant_iteratorsa> friend struct __detail::_Insert; public: @@ -308,6 +311,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using const_local_iterator = typename __hashtable_base:: const_local_iterator; +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Value, __node_alloc_type>; + using insert_return_type = _Node_insert_return<iterator, node_type>; +#endif + private: __bucket_type* _M_buckets = &_M_single_bucket; size_type _M_bucket_count = 1; @@ -475,8 +483,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(_Hashtable&) - noexcept(__is_nothrow_swappable<_H1>::value - && __is_nothrow_swappable<_Equal>::value); + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value); // Basic container operations iterator @@ -762,6 +770,135 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 1189. // reserve, if present, comes from _Rehash_base. +#if __cplusplus > 201402L + /// Re-insert an extracted node into a container with unique keys. + insert_return_type + _M_reinsert_node(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + const key_type& __k = __nh._M_key(); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (__node_type* __n = _M_find_node(__bkt, __k, __code)) + { + __ret.node = std::move(__nh); + __ret.position = iterator(__n); + __ret.inserted = false; + } + else + { + __ret.position + = _M_insert_unique_node(__bkt, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + } + return __ret; + } + + /// Re-insert an extracted node into a container with equivalent keys. + iterator + _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + auto __code = this->_M_hash_code(__nh._M_key()); + auto __node = std::exchange(__nh._M_ptr, nullptr); + // FIXME: this deallocates the node on exception. + __ret = _M_insert_multi_node(__hint._M_cur, __code, __node); + } + return __ret; + } + + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __node_type* __n = __pos._M_cur; + size_t __bkt = _M_bucket_index(__n); + + // Look for previous node to unlink it from the erased one, this + // is why we need buckets to contain the before begin to make + // this search fast. + __node_base* __prev_n = _M_get_previous_node(__bkt, __n); + + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n->_M_next(), + __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); + else if (__n->_M_nxt) + { + size_type __next_bkt = _M_bucket_index(__n->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + } + + __prev_n->_M_nxt = __n->_M_nxt; + __n->_M_nxt = nullptr; + --_M_element_count; + return { __n, this->_M_node_allocator() }; + } + + /// Extract a node. + node_type + extract(const _Key& __k) + { + node_type __nh; + auto __pos = find(__k); + if (__pos != end()) + __nh = extract(const_iterator(__pos)); + return __nh; + } + + /// Merge from a compatible container into one with unique keys. + template<typename _Compatible_Hashtable> + void + _M_merge_unique(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v<typename _Compatible_Hashtable::node_type, + node_type>, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + const key_type& __k = this->_M_extract()(__pos._M_cur->_M_v()); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (_M_find_node(__bkt, __k, __code) == nullptr) + { + auto __nh = __src.extract(__pos); + _M_insert_unique_node(__bkt, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + } + } + } + + /// Merge from a compatible container into one with equivalent keys. + template<typename _Compatible_Hashtable> + void + _M_merge_multi(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v<typename _Compatible_Hashtable::node_type, + node_type>, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + this->reserve(size() + __src.size()); + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + _M_reinsert_node_multi(cend(), __src.extract(__i++)); + } +#endif // C++17 + private: // Helper rehash method used when keys are unique. void _M_rehash_aux(size_type __n, std::true_type); @@ -1236,8 +1373,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: swap(_Hashtable& __x) - noexcept(__is_nothrow_swappable<_H1>::value - && __is_nothrow_swappable<_Equal>::value) + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value) { // The only base class with member variables is hash_code_base. // We define _Hash_code_base::_M_swap because different @@ -2078,6 +2215,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_buckets = __new_buckets; } +#if __cplusplus > 201402L + template<typename, typename, typename> class _Hash_merge_helper { }; +#endif // C++17 + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index 7a2ac92f83..8af8c498de 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -1,6 +1,6 @@ // Internal policy header for unordered_set and unordered_map -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -31,6 +31,8 @@ #ifndef _HASHTABLE_POLICY_H #define _HASHTABLE_POLICY_H 1 +#include <bits/stl_algobase.h> // for std::min. + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -457,6 +459,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// smallest prime that keeps the load factor small enough. struct _Prime_rehash_policy { + using __has_load_factor = std::true_type; + _Prime_rehash_policy(float __z = 1.0) noexcept : _M_max_load_factor(__z), _M_next_resize(0) { } @@ -501,6 +505,132 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION mutable std::size_t _M_next_resize; }; + /// Range hashing function assuming that second arg is a power of 2. + struct _Mask_range_hashing + { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef std::size_t result_type; + + result_type + operator()(first_argument_type __num, + second_argument_type __den) const noexcept + { return __num & (__den - 1); } + }; + + /// Compute closest power of 2. + _GLIBCXX14_CONSTEXPR + inline std::size_t + __clp2(std::size_t __n) noexcept + { +#if __SIZEOF_SIZE_T__ >= 8 + std::uint_fast64_t __x = __n; +#else + std::uint_fast32_t __x = __n; +#endif + // Algorithm from Hacker's Delight, Figure 3-3. + __x = __x - 1; + __x = __x | (__x >> 1); + __x = __x | (__x >> 2); + __x = __x | (__x >> 4); + __x = __x | (__x >> 8); + __x = __x | (__x >>16); +#if __SIZEOF_SIZE_T__ >= 8 + __x = __x | (__x >>32); +#endif + return __x + 1; + } + + /// Rehash policy providing power of 2 bucket numbers. Avoids modulo + /// operations. + struct _Power2_rehash_policy + { + using __has_load_factor = std::true_type; + + _Power2_rehash_policy(float __z = 1.0) noexcept + : _M_max_load_factor(__z), _M_next_resize(0) { } + + float + max_load_factor() const noexcept + { return _M_max_load_factor; } + + // Return a bucket size no smaller than n (as long as n is not above the + // highest power of 2). + std::size_t + _M_next_bkt(std::size_t __n) noexcept + { + const auto __max_width = std::min<size_t>(sizeof(size_t), 8); + const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1); + std::size_t __res = __clp2(__n); + + if (__res == __n) + __res <<= 1; + + if (__res == 0) + __res = __max_bkt; + + if (__res == __max_bkt) + // Set next resize to the max value so that we never try to rehash again + // as we already reach the biggest possible bucket number. + // Note that it might result in max_load_factor not being respected. + _M_next_resize = std::size_t(-1); + else + _M_next_resize + = __builtin_ceil(__res * (long double)_M_max_load_factor); + + return __res; + } + + // Return a bucket count appropriate for n elements + std::size_t + _M_bkt_for_elements(std::size_t __n) const noexcept + { return __builtin_ceil(__n / (long double)_M_max_load_factor); } + + // __n_bkt is current bucket count, __n_elt is current element count, + // and __n_ins is number of elements to be inserted. Do we need to + // increase bucket count? If so, return make_pair(true, n), where n + // is the new bucket count. If not, return make_pair(false, 0). + std::pair<bool, std::size_t> + _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, + std::size_t __n_ins) noexcept + { + if (__n_elt + __n_ins >= _M_next_resize) + { + long double __min_bkts = (__n_elt + __n_ins) + / (long double)_M_max_load_factor; + if (__min_bkts >= __n_bkt) + return std::make_pair(true, + _M_next_bkt(std::max<std::size_t>(__builtin_floor(__min_bkts) + 1, + __n_bkt * _S_growth_factor))); + + _M_next_resize + = __builtin_floor(__n_bkt * (long double)_M_max_load_factor); + return std::make_pair(false, 0); + } + else + return std::make_pair(false, 0); + } + + typedef std::size_t _State; + + _State + _M_state() const noexcept + { return _M_next_resize; } + + void + _M_reset() noexcept + { _M_next_resize = 0; } + + void + _M_reset(_State __state) noexcept + { _M_next_resize = __state; } + + static const std::size_t _S_growth_factor = 2; + + float _M_max_load_factor; + std::size_t _M_next_resize; + }; + // Base classes for std::_Hashtable. We define these base classes // because in some cases we want to do different things depending on // the value of a policy class. In some cases the policy class @@ -667,7 +797,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Primary class template _Insert_base. * - * insert member functions appropriate to all _Hashtables. + * Defines @c insert member functions appropriate to all _Hashtables. */ template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, @@ -769,14 +899,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Primary class template _Insert. * - * Select insert member functions appropriate to _Hashtable policy choices. + * Defines @c insert member functions that depend on _Hashtable policies, + * via partial specializations. */ template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, typename _Traits, - bool _Constant_iterators = _Traits::__constant_iterators::value, - bool _Unique_keys = _Traits::__unique_keys::value> + bool _Constant_iterators = _Traits::__constant_iterators::value> struct _Insert; /// Specialization. @@ -785,65 +915,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _H1, typename _H2, typename _Hash, typename _RehashPolicy, typename _Traits> struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits, true, true> + _RehashPolicy, _Traits, true> : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits> { using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>; - using value_type = typename __base_type::value_type; - using iterator = typename __base_type::iterator; - using const_iterator = typename __base_type::const_iterator; - - using __unique_keys = typename __base_type::__unique_keys; - using __hashtable = typename __base_type::__hashtable; - using __node_gen_type = typename __base_type::__node_gen_type; - - using __base_type::insert; - std::pair<iterator, bool> - insert(value_type&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(std::move(__v), __node_gen, __unique_keys()); - } - - iterator - insert(const_iterator __hint, value_type&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(__hint, std::move(__v), __node_gen, - __unique_keys()); - } - }; + using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _Traits>; - /// Specialization. - template<typename _Key, typename _Value, typename _Alloc, - typename _ExtractKey, typename _Equal, - typename _H1, typename _H2, typename _Hash, - typename _RehashPolicy, typename _Traits> - struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits, true, false> - : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits> - { - using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; using value_type = typename __base_type::value_type; using iterator = typename __base_type::iterator; using const_iterator = typename __base_type::const_iterator; using __unique_keys = typename __base_type::__unique_keys; + using __ireturn_type = typename __hashtable_base::__ireturn_type; using __hashtable = typename __base_type::__hashtable; using __node_gen_type = typename __base_type::__node_gen_type; using __base_type::insert; - iterator + __ireturn_type insert(value_type&& __v) { __hashtable& __h = this->_M_conjure_hashtable(); @@ -865,9 +960,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, - typename _RehashPolicy, typename _Traits, bool _Unique_keys> + typename _RehashPolicy, typename _Traits> struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits, false, _Unique_keys> + _RehashPolicy, _Traits, false> : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits> { @@ -911,28 +1006,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + template<typename _Policy> + using __has_load_factor = typename _Policy::__has_load_factor; + /** * Primary class template _Rehash_base. * * Give hashtable the max_load_factor functions and reserve iff the - * rehash policy is _Prime_rehash_policy. + * rehash policy supports it. */ template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _H1, typename _H2, typename _Hash, - typename _RehashPolicy, typename _Traits> + typename _RehashPolicy, typename _Traits, + typename = + __detected_or_t<std::false_type, __has_load_factor, _RehashPolicy>> struct _Rehash_base; - /// Specialization. + /// Specialization when rehash policy doesn't provide load factor management. template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, - typename _H1, typename _H2, typename _Hash, typename _Traits> + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> + struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, + std::false_type> + { + }; + + /// Specialization when rehash policy provide load factor management. + template<typename _Key, typename _Value, typename _Alloc, + typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _Prime_rehash_policy, _Traits> + _H1, _H2, _Hash, _RehashPolicy, _Traits, + std::true_type> { using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _Prime_rehash_policy, _Traits>; + _RehashPolicy, _Traits>; float max_load_factor() const noexcept @@ -945,7 +1058,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION max_load_factor(float __z) { __hashtable* __this = static_cast<__hashtable*>(this); - __this->__rehash_policy(_Prime_rehash_policy(__z)); + __this->__rehash_policy(_RehashPolicy(__z)); } void diff --git a/libstdc++-v3/include/bits/indirect_array.h b/libstdc++-v3/include/bits/indirect_array.h index 4eae4dc445..ed799707e8 100644 --- a/libstdc++-v3/include/bits/indirect_array.h +++ b/libstdc++-v3/include/bits/indirect_array.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- indirect_array class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h new file mode 100644 index 0000000000..eba8707435 --- /dev/null +++ b/libstdc++-v3/include/bits/invoke.h @@ -0,0 +1,104 @@ +// Implementation of INVOKE -*- C++ -*- + +// Copyright (C) 2016-2017 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 include/bits/invoke.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_INVOKE_H +#define _GLIBCXX_INVOKE_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include <bits/c++0x_warning.h> +#else + +#include <type_traits> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // Used by __invoke_impl instead of std::forward<_Tp> so that a + // reference_wrapper is converted to an lvalue-reference. + template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type> + constexpr _Up&& + __invfwd(typename remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Up&&>(__t); } + + template<typename _Res, typename _Fn, typename... _Args> + constexpr _Res + __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) + { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } + + template<typename _Res, typename _MemFun, typename _Tp, typename... _Args> + constexpr _Res + __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } + + template<typename _Res, typename _MemFun, typename _Tp, typename... _Args> + constexpr _Res + __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { + return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); + } + + template<typename _Res, typename _MemPtr, typename _Tp> + constexpr _Res + __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) + { return __invfwd<_Tp>(__t).*__f; } + + template<typename _Res, typename _MemPtr, typename _Tp> + constexpr _Res + __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) + { return (*std::forward<_Tp>(__t)).*__f; } + + /// Invoke a callable object. + template<typename _Callable, typename... _Args> + constexpr typename __invoke_result<_Callable, _Args...>::type + __invoke(_Callable&& __fn, _Args&&... __args) + noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_INVOKE_H diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index 97210d28f9..e5a107db4b 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -1,6 +1,6 @@ // Iostreams base classes -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -52,8 +52,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // The following definitions of bitmask types are enums, not ints, // as permitted (but not required) in the standard, in order to provide - // better type safety in iostream calls. A side effect is that - // expressions involving them are no longer compile-time constants. + // better type safety in iostream calls. A side effect is that in C++98 + // expressions involving them are not compile-time constants. enum _Ios_Fmtflags { _S_boolalpha = 1L << 0, @@ -207,12 +207,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const error_category& iostream_category() noexcept; inline error_code - make_error_code(io_errc e) noexcept - { return error_code(static_cast<int>(e), iostream_category()); } + make_error_code(io_errc __e) noexcept + { return error_code(static_cast<int>(__e), iostream_category()); } inline error_condition - make_error_condition(io_errc e) noexcept - { return error_condition(static_cast<int>(e), iostream_category()); } + make_error_condition(io_errc __e) noexcept + { return error_condition(static_cast<int>(__e), iostream_category()); } #endif // 27.4.2 Class ios_base diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index bc962adc94..b390f743bb 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -1,6 +1,6 @@ // istream classes -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc index 8b3fe00cfc..fcb8353e09 100644 --- a/libstdc++-v3/include/bits/list.tcc +++ b/libstdc++-v3/include/bits/list.tcc @@ -1,6 +1,6 @@ // List implementation (out of line) -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -380,26 +380,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // 300. list::merge() specification incomplete if (this != std::__addressof(__x)) { - _M_check_equal_allocators(__x); + _M_check_equal_allocators(__x); iterator __first1 = begin(); iterator __last1 = end(); iterator __first2 = __x.begin(); iterator __last2 = __x.end(); - while (__first1 != __last1 && __first2 != __last2) - if (*__first2 < *__first1) - { - iterator __next = __first2; - _M_transfer(__first1, __first2, ++__next); - __first2 = __next; - } - else - ++__first1; - if (__first2 != __last2) - _M_transfer(__last1, __first2, __last2); + const size_t __orig_size = __x.size(); + __try { + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); - this->_M_inc_size(__x._M_get_size()); - __x._M_set_size(0); + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } } } @@ -423,20 +433,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator __last1 = end(); iterator __first2 = __x.begin(); iterator __last2 = __x.end(); - while (__first1 != __last1 && __first2 != __last2) - if (__comp(*__first2, *__first1)) - { - iterator __next = __first2; - _M_transfer(__first1, __first2, ++__next); - __first2 = __next; - } - else - ++__first1; - if (__first2 != __last2) - _M_transfer(__last1, __first2, __last2); - - this->_M_inc_size(__x._M_get_size()); - __x._M_set_size(0); + const size_t __orig_size = __x.size(); + __try + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } } } @@ -453,27 +474,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER list __tmp[64]; list * __fill = __tmp; list * __counter; - - do + __try { - __carry.splice(__carry.begin(), *this, begin()); - - for(__counter = __tmp; - __counter != __fill && !__counter->empty(); - ++__counter) + do { - __counter->merge(__carry); + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry); + __carry.swap(*__counter); + } __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; } - __carry.swap(*__counter); - if (__counter == __fill) - ++__fill; - } - while ( !empty() ); + while ( !empty() ); - for (__counter = __tmp + 1; __counter != __fill; ++__counter) - __counter->merge(*(__counter - 1)); - swap( *(__fill - 1) ); + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1)); + swap( *(__fill - 1) ); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } } } @@ -530,27 +560,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER list __tmp[64]; list * __fill = __tmp; list * __counter; - - do + __try { - __carry.splice(__carry.begin(), *this, begin()); - - for(__counter = __tmp; - __counter != __fill && !__counter->empty(); - ++__counter) + do { - __counter->merge(__carry, __comp); + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry, __comp); + __carry.swap(*__counter); + } __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; } - __carry.swap(*__counter); - if (__counter == __fill) - ++__fill; - } - while ( !empty() ); + while ( !empty() ); - for (__counter = __tmp + 1; __counter != __fill; ++__counter) - __counter->merge(*(__counter - 1), __comp); - swap(*(__fill - 1)); + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1), __comp); + swap(*(__fill - 1)); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } } } diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h index 04b4ab3b1d..b63e9c8a3e 100644 --- a/libstdc++-v3/include/bits/locale_classes.h +++ b/libstdc++-v3/include/bits/locale_classes.h @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -461,10 +461,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - class __shim; - const facet* _M_sso_shim(const id*) const; const facet* _M_cow_shim(const id*) const; + + protected: + class __shim; // For internal use only. }; diff --git a/libstdc++-v3/include/bits/locale_classes.tcc b/libstdc++-v3/include/bits/locale_classes.tcc index 8e9426a8b9..71378f68b2 100644 --- a/libstdc++-v3/include/bits/locale_classes.tcc +++ b/libstdc++-v3/include/bits/locale_classes.tcc @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h index d4bec2fa8b..9b952d4516 100644 --- a/libstdc++-v3/include/bits/locale_conv.h +++ b/libstdc++-v3/include/bits/locale_conv.h @@ -1,6 +1,6 @@ // wstring_convert implementation -*- C++ -*- -// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// Copyright (C) 2015-2017 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 @@ -81,7 +81,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && (__outstr.size() - __outchars) < __maxlen); if (__result == codecvt_base::error) - return false; + { + __count = __next - __first; + return false; + } if (__result == codecvt_base::noconv) { diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index e3e206b7d4..1ad0eb5ab6 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -1128,7 +1128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @return The converted char. */ virtual char - do_narrow(char_type __c, char __dfault) const + do_narrow(char_type __c, char __dfault __attribute__((__unused__))) const { return __c; } /** @@ -1155,7 +1155,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ virtual const char_type* do_narrow(const char_type* __lo, const char_type* __hi, - char __dfault, char* __to) const + char __dfault __attribute__((__unused__)), char* __to) const { __builtin_memcpy(__to, __lo, __hi - __lo); return __hi; diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index c9523ec315..351190ccb0 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.h b/libstdc++-v3/include/bits/locale_facets_nonio.h index 5685d72aff..0cd307fb5e 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.h +++ b/libstdc++-v3/include/bits/locale_facets_nonio.h @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 1a4f9a0e66..a449c41e6b 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -659,30 +659,38 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 // Abbreviated weekday name [tm_wday] const char_type* __days1[7]; __tp._M_days_abbreviated(__days1); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, + __beg = _M_extract_name(__beg, __end, __mem, __days1, 7, __io, __tmperr); + if (!__tmperr) + __tm->tm_wday = __mem; break; case 'A': // Weekday name [tm_wday]. const char_type* __days2[7]; __tp._M_days(__days2); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, + __beg = _M_extract_name(__beg, __end, __mem, __days2, 7, __io, __tmperr); + if (!__tmperr) + __tm->tm_wday = __mem; break; case 'h': case 'b': // Abbreviated month name [tm_mon] const char_type* __months1[12]; __tp._M_months_abbreviated(__months1); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, + __beg = _M_extract_name(__beg, __end, __mem, __months1, 12, __io, __tmperr); + if (!__tmperr) + __tm->tm_mon = __mem; break; case 'B': // Month name [tm_mon]. const char_type* __months2[12]; __tp._M_months(__months2); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, + __beg = _M_extract_name(__beg, __end, __mem, __months2, 12, __io, __tmperr); + if (!__tmperr) + __tm->tm_mon = __mem; break; case 'c': // Default time and date representation. @@ -693,18 +701,22 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'd': // Day [01, 31]. [tm_mday] - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, + __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, __io, __tmperr); + if (!__tmperr) + __tm->tm_mday = __mem; break; case 'e': // Day [1, 31], with single digits preceded by // space. [tm_mday] if (__ctype.is(ctype_base::space, *__beg)) - __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, + __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, 1, __io, __tmperr); else - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, + __beg = _M_extract_num(__beg, __end, __mem, 10, 31, 2, __io, __tmperr); + if (!__tmperr) + __tm->tm_mday = __mem; break; case 'D': // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] @@ -715,13 +727,17 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'H': // Hour [00, 23]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, + __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, __io, __tmperr); + if (!__tmperr) + __tm->tm_hour = __mem; break; case 'I': // Hour [01, 12]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, + __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, __io, __tmperr); + if (!__tmperr) + __tm->tm_hour = __mem; break; case 'm': // Month [01, 12]. [tm_mon] @@ -732,8 +748,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'M': // Minute [00, 59]. [tm_min] - __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, + __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, __io, __tmperr); + if (!__tmperr) + __tm->tm_min = __mem; break; case 'n': if (__ctype.narrow(*__beg, 0) == '\n') @@ -752,11 +770,13 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 // Seconds. [tm_sec] // [00, 60] in C99 (one leap-second), [00, 61] in C89. #if _GLIBCXX_USE_C99 - __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2, + __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, #else - __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2, + __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, #endif __io, __tmperr); + if (!__tmperr) + __tm->tm_sec = __mem; break; case 't': if (__ctype.narrow(*__beg, 0) == '\t') diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h index 61579d45ff..ae302e26e1 100644 --- a/libstdc++-v3/include/bits/localefwd.h +++ b/libstdc++-v3/include/bits/localefwd.h @@ -1,6 +1,6 @@ // <locale> Forward declarations -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/mask_array.h b/libstdc++-v3/include/bits/mask_array.h index ba7828266c..5c4fcc6763 100644 --- a/libstdc++-v3/include/bits/mask_array.h +++ b/libstdc++-v3/include/bits/mask_array.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- mask_array class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -136,8 +136,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template<typename _Tp> - inline mask_array<_Tp>::mask_array(const mask_array<_Tp>& a) - : _M_sz(a._M_sz), _M_mask(a._M_mask), _M_array(a._M_array) {} + inline mask_array<_Tp>::mask_array(const mask_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_mask(__a._M_mask), _M_array(__a._M_array) {} template<typename _Tp> inline diff --git a/libstdc++-v3/include/bits/memoryfwd.h b/libstdc++-v3/include/bits/memoryfwd.h index 8ef0076cbc..1429026c4c 100644 --- a/libstdc++-v3/include/bits/memoryfwd.h +++ b/libstdc++-v3/include/bits/memoryfwd.h @@ -1,6 +1,6 @@ // <memory> Forward declarations -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index afcea2d846..5f47b0e7ba 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -1,6 +1,6 @@ -// Move, forward and identity for C++0x + swap -*- C++ -*- +// Move, forward and identity for C++11 + swap -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -43,12 +43,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup utilities */ template<typename _Tp> - inline _Tp* + inline _GLIBCXX_CONSTEXPR _Tp* __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT - { - return reinterpret_cast<_Tp*> - (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r))); - } + { return __builtin_addressof(__r); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -123,6 +120,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // declval, from type_traits. +#if __cplusplus > 201402L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2296. std::addressof should be constexpr +# define __cpp_lib_addressof_constexpr 201603 +#endif /** * @brief Returns the actual address of the object or function * referenced by r, even in the presence of an overloaded @@ -131,10 +133,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @return The actual address. */ template<typename _Tp> - inline _Tp* + inline _GLIBCXX17_CONSTEXPR _Tp* addressof(_Tp& __r) noexcept { return std::__addressof(__r); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2598. addressof works on temporaries + template<typename _Tp> + const _Tp* addressof(const _Tp&&) = delete; + // C++11 version of std::exchange for internal use. template <typename _Tp, typename _Up = _Tp> inline _Tp @@ -174,7 +181,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> inline #if __cplusplus >= 201103L - typename enable_if<__and_<is_move_constructible<_Tp>, + typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value>::type swap(_Tp& __a, _Tp& __b) noexcept(__and_<is_nothrow_move_constructible<_Tp>, diff --git a/libstdc++-v3/include/bits/node_handle.h b/libstdc++-v3/include/bits/node_handle.h new file mode 100644 index 0000000000..44a92644cd --- /dev/null +++ b/libstdc++-v3/include/bits/node_handle.h @@ -0,0 +1,328 @@ +// Node handles for containers -*- C++ -*- + +// Copyright (C) 2016-2017 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/node_handle.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + * @headername{map,set,unordered_map,unordered_set} + */ + +#ifndef _NODE_HANDLE +#define _NODE_HANDLE 1 + +#pragma GCC system_header + +#if __cplusplus > 201402L +# define __cpp_lib_node_extract 201606 + +#include <optional> +#include <tuple> +#include <bits/alloc_traits.h> +#include <bits/ptr_traits.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Base class for node handle types of maps and sets. + template<typename _Val, typename _NodeAlloc> + class _Node_handle_common + { + using _AllocTraits = allocator_traits<_NodeAlloc>; + + public: + using allocator_type = __alloc_rebind<_NodeAlloc, _Val>; + + allocator_type + get_allocator() const noexcept + { + __glibcxx_assert(!this->empty()); + return allocator_type(*_M_alloc); + } + + explicit operator bool() const noexcept { return _M_ptr != nullptr; } + + bool empty() const noexcept { return _M_ptr == nullptr; } + + protected: + constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {} + + ~_Node_handle_common() { _M_destroy(); } + + _Node_handle_common(_Node_handle_common&& __nh) noexcept + : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc)) + { + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + } + + _Node_handle_common& + operator=(_Node_handle_common&& __nh) noexcept + { + _M_destroy(); + _M_ptr = __nh._M_ptr; + if constexpr (is_move_assignable_v<_NodeAlloc>) + { + if (_AllocTraits::propagate_on_container_move_assignment::value + || !this->_M_alloc) + this->_M_alloc = std::move(__nh._M_alloc); + else + __glibcxx_assert(this->_M_alloc == __nh._M_alloc); + } + else + __glibcxx_assert(_M_alloc); + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + return *this; + } + + _Node_handle_common(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _M_ptr(__ptr), _M_alloc(__alloc) { } + + void + _M_swap(_Node_handle_common& __nh) noexcept + { + using std::swap; + swap(_M_ptr, __nh._M_ptr); + if (_AllocTraits::propagate_on_container_swap + || !_M_alloc || !__nh._M_alloc) + _M_alloc.swap(__nh._M_alloc); + else + __glibcxx_assert(_M_alloc == __nh._M_alloc); + } + + private: + void + _M_destroy() noexcept + { + if (_M_ptr != nullptr) + { + allocator_type __alloc(*_M_alloc); + allocator_traits<allocator_type>::destroy(__alloc, + _M_ptr->_M_valptr()); + _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1); + } + } + + protected: + typename _AllocTraits::pointer _M_ptr; + private: + optional<_NodeAlloc> _M_alloc; + + template<typename _Key2, typename _Value2, typename _KeyOfValue, + typename _Compare, typename _ValueAlloc> + friend class _Rb_tree; + }; + + /// Node handle type for maps. + template<typename _Key, typename _Value, typename _NodeAlloc> + class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using key_type = _Key; + using mapped_type = typename _Value::second_type; + + key_type& + key() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pkey; + } + + mapped_type& + mapped() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pmapped; + } + + void + swap(_Node_handle& __nh) noexcept + { + this->_M_swap(__nh); + using std::swap; + swap(_M_pkey, __nh._M_pkey); + swap(_M_pmapped, __nh._M_pmapped); + } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) + { + if (__ptr) + { + auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first); + _M_pkey = _S_pointer_to(__key); + _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second); + } + else + { + _M_pkey = nullptr; + _M_pmapped = nullptr; + } + } + + template<typename _Tp> + using __pointer = __ptr_rebind<typename _AllocTraits::pointer, _Tp>; + + __pointer<_Key> _M_pkey = nullptr; + __pointer<typename _Value::second_type> _M_pmapped = nullptr; + + template<typename _Tp> + __pointer<_Tp> + _S_pointer_to(_Tp& __obj) + { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); } + + const key_type& + _M_key() const noexcept { return key(); } + + template<typename _Key2, typename _Value2, typename _KeyOfValue, + typename _Compare, typename _ValueAlloc> + friend class _Rb_tree; + + template<typename _Key2, typename _Value2, typename _ValueAlloc, + typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> + friend class _Hashtable; + }; + + /// Node handle type for sets. + template<typename _Value, typename _NodeAlloc> + class _Node_handle<_Value, _Value, _NodeAlloc> + : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using value_type = _Value; + + value_type& + value() const noexcept + { + __glibcxx_assert(!this->empty()); + return *this->_M_ptr->_M_valptr(); + } + + void + swap(_Node_handle& __nh) noexcept + { this->_M_swap(__nh); } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { } + + const value_type& + _M_key() const noexcept { return value(); } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + friend class _Rb_tree; + + template<typename _Key2, typename _Value2, typename _ValueAlloc, + typename _ExtractKey, typename _Equal, + typename _H1, typename _H2, typename _Hash, + typename _RehashPolicy, typename _Traits> + friend class _Hashtable; + }; + + /// Return type of insert(node_handle&&) on unique maps/sets. + template<typename _Iterator, typename _NodeHandle> + struct _Node_insert_return + { + bool inserted = false; + _Iterator position = _Iterator(); + _NodeHandle node; + + template<size_t _Idx> + decltype(auto) get() & + { return std::get<_Idx>(std::tie(inserted, position, node)); } + + template<size_t _Idx> + decltype(auto) get() const & + { return std::get<_Idx>(std::tie(inserted, position, node)); } + + template<size_t _Idx> + decltype(auto) get() && + { + return std::move(std::get<_Idx>(std::tie(inserted, position, node))); + } + + template<size_t _Idx> + decltype(auto) get() const && + { + return std::move(std::get<_Idx>(std::tie(inserted, position, node))); + } + }; + + template<typename _Iterator, typename _NodeHandle> + struct tuple_size<_Node_insert_return<_Iterator, _NodeHandle>> + : integral_constant<size_t, 3> { }; + + template<typename _Iterator, typename _NodeHandle> + struct tuple_element<0, _Node_insert_return<_Iterator, _NodeHandle>> + { using type = bool; }; + + template<typename _Iterator, typename _NodeHandle> + struct tuple_element<1, _Node_insert_return<_Iterator, _NodeHandle>> + { using type = _Iterator; }; + + template<typename _Iterator, typename _NodeHandle> + struct tuple_element<2, _Node_insert_return<_Iterator, _NodeHandle>> + { using type = _NodeHandle; }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc index c3a4ec3a66..e96bad8121 100644 --- a/libstdc++-v3/include/bits/ostream.tcc +++ b/libstdc++-v3/include/bits/ostream.tcc @@ -1,6 +1,6 @@ // ostream classes -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/ostream_insert.h b/libstdc++-v3/include/bits/ostream_insert.h index 8ff0a4519c..8c9b941a16 100644 --- a/libstdc++-v3/include/bits/ostream_insert.h +++ b/libstdc++-v3/include/bits/ostream_insert.h @@ -1,6 +1,6 @@ // Helpers for ostream inserters -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h index 7aa43fc2ba..b82df75510 100644 --- a/libstdc++-v3/include/bits/parse_numbers.h +++ b/libstdc++-v3/include/bits/parse_numbers.h @@ -1,6 +1,6 @@ // Components for compile-time parsing of numbers -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 diff --git a/libstdc++-v3/include/bits/postypes.h b/libstdc++-v3/include/bits/postypes.h index f63571eeb8..818086313f 100644 --- a/libstdc++-v3/include/bits/postypes.h +++ b/libstdc++-v3/include/bits/postypes.h @@ -1,6 +1,6 @@ // Position types -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -41,7 +41,7 @@ // XXX If <stdint.h> is really needed, make sure to define the macros // before including it, in order not to break <tr1/cstdint> (and <cstdint> -// in C++0x). Reconsider all this as soon as possible... +// in C++11). Reconsider all this as soon as possible... #if (defined(_GLIBCXX_HAVE_INT64_T) && !defined(_GLIBCXX_HAVE_INT64_T_LONG) \ && !defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)) diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h index 3c4cb6d26a..0624a38a1b 100644 --- a/libstdc++-v3/include/bits/predefined_ops.h +++ b/libstdc++-v3/include/bits/predefined_ops.h @@ -1,6 +1,6 @@ // Default predicates for internal use -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -24,7 +24,7 @@ /** @file predefined_ops.h * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. + * You should not attempt to use it directly. @headername{algorithm} */ #ifndef _GLIBCXX_PREDEFINED_OPS_H @@ -42,6 +42,7 @@ namespace __ops operator()(_Iterator1 __it1, _Iterator2 __it2) const { return *__it1 < *__it2; } }; + _GLIBCXX14_CONSTEXPR inline _Iter_less_iter __iter_less_iter() @@ -49,11 +50,20 @@ namespace __ops struct _Iter_less_val { +#if __cplusplus >= 201103L + constexpr _Iter_less_val() = default; +#else + _Iter_less_val() { } +#endif + + explicit + _Iter_less_val(_Iter_less_iter) { } + template<typename _Iterator, typename _Value> bool operator()(_Iterator __it, _Value& __val) const { return *__it < __val; } - }; + }; inline _Iter_less_val __iter_less_val() @@ -65,11 +75,20 @@ namespace __ops struct _Val_less_iter { +#if __cplusplus >= 201103L + constexpr _Val_less_iter() = default; +#else + _Val_less_iter() { } +#endif + + explicit + _Val_less_iter(_Iter_less_iter) { } + template<typename _Value, typename _Iterator> bool operator()(_Value& __val, _Iterator __it) const { return __val < *__it; } - }; + }; inline _Val_less_iter __val_less_iter() @@ -85,7 +104,7 @@ namespace __ops bool operator()(_Iterator1 __it1, _Iterator2 __it2) const { return *__it1 == *__it2; } - }; + }; inline _Iter_equal_to_iter __iter_equal_to_iter() @@ -97,7 +116,7 @@ namespace __ops bool operator()(_Iterator __it, _Value& __val) const { return *__it == __val; } - }; + }; inline _Iter_equal_to_val __iter_equal_to_val() @@ -111,9 +130,10 @@ namespace __ops struct _Iter_comp_iter { _Compare _M_comp; - _GLIBCXX14_CONSTEXPR + + explicit _GLIBCXX14_CONSTEXPR _Iter_comp_iter(_Compare __comp) - : _M_comp(__comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) { } template<typename _Iterator1, typename _Iterator2> @@ -127,17 +147,30 @@ namespace __ops _GLIBCXX14_CONSTEXPR inline _Iter_comp_iter<_Compare> __iter_comp_iter(_Compare __comp) - { return _Iter_comp_iter<_Compare>(__comp); } + { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } template<typename _Compare> struct _Iter_comp_val { _Compare _M_comp; + explicit _Iter_comp_val(_Compare __comp) - : _M_comp(__comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + explicit + _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) { } +#if __cplusplus >= 201103L + explicit + _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + template<typename _Iterator, typename _Value> bool operator()(_Iterator __it, _Value& __val) @@ -147,22 +180,35 @@ namespace __ops template<typename _Compare> inline _Iter_comp_val<_Compare> __iter_comp_val(_Compare __comp) - { return _Iter_comp_val<_Compare>(__comp); } + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } template<typename _Compare> inline _Iter_comp_val<_Compare> __iter_comp_val(_Iter_comp_iter<_Compare> __comp) - { return _Iter_comp_val<_Compare>(__comp._M_comp); } + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } template<typename _Compare> struct _Val_comp_iter { _Compare _M_comp; + explicit _Val_comp_iter(_Compare __comp) - : _M_comp(__comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) { } + explicit + _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + explicit + _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + template<typename _Value, typename _Iterator> bool operator()(_Value& __val, _Iterator __it) @@ -172,18 +218,19 @@ namespace __ops template<typename _Compare> inline _Val_comp_iter<_Compare> __val_comp_iter(_Compare __comp) - { return _Val_comp_iter<_Compare>(__comp); } + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } template<typename _Compare> inline _Val_comp_iter<_Compare> __val_comp_iter(_Iter_comp_iter<_Compare> __comp) - { return _Val_comp_iter<_Compare>(__comp._M_comp); } + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } template<typename _Value> struct _Iter_equals_val { _Value& _M_value; + explicit _Iter_equals_val(_Value& __value) : _M_value(__value) { } @@ -202,16 +249,17 @@ namespace __ops template<typename _Iterator1> struct _Iter_equals_iter { - typename std::iterator_traits<_Iterator1>::reference _M_ref; + _Iterator1 _M_it1; + explicit _Iter_equals_iter(_Iterator1 __it1) - : _M_ref(*__it1) + : _M_it1(__it1) { } template<typename _Iterator2> bool operator()(_Iterator2 __it2) - { return *__it2 == _M_ref; } + { return *__it2 == *_M_it1; } }; template<typename _Iterator> @@ -224,8 +272,9 @@ namespace __ops { _Predicate _M_pred; + explicit _Iter_pred(_Predicate __pred) - : _M_pred(__pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) { } template<typename _Iterator> @@ -237,7 +286,7 @@ namespace __ops template<typename _Predicate> inline _Iter_pred<_Predicate> __pred_iter(_Predicate __pred) - { return _Iter_pred<_Predicate>(__pred); } + { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } template<typename _Compare, typename _Value> struct _Iter_comp_to_val @@ -246,7 +295,7 @@ namespace __ops _Value& _M_value; _Iter_comp_to_val(_Compare __comp, _Value& __value) - : _M_comp(__comp), _M_value(__value) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) { } template<typename _Iterator> @@ -258,36 +307,42 @@ namespace __ops template<typename _Compare, typename _Value> _Iter_comp_to_val<_Compare, _Value> __iter_comp_val(_Compare __comp, _Value &__val) - { return _Iter_comp_to_val<_Compare, _Value>(__comp, __val); } + { + return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); + } template<typename _Compare, typename _Iterator1> struct _Iter_comp_to_iter { _Compare _M_comp; - typename std::iterator_traits<_Iterator1>::reference _M_ref; + _Iterator1 _M_it1; _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) - : _M_comp(__comp), _M_ref(*__it1) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) { } template<typename _Iterator2> bool operator()(_Iterator2 __it2) - { return bool(_M_comp(*__it2, _M_ref)); } + { return bool(_M_comp(*__it2, *_M_it1)); } }; template<typename _Compare, typename _Iterator> inline _Iter_comp_to_iter<_Compare, _Iterator> __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) - { return _Iter_comp_to_iter<_Compare, _Iterator>(__comp._M_comp, __it); } + { + return _Iter_comp_to_iter<_Compare, _Iterator>( + _GLIBCXX_MOVE(__comp._M_comp), __it); + } template<typename _Predicate> struct _Iter_negate { _Predicate _M_pred; + explicit _Iter_negate(_Predicate __pred) - : _M_pred(__pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) { } template<typename _Iterator> @@ -299,7 +354,7 @@ namespace __ops template<typename _Predicate> inline _Iter_negate<_Predicate> __negate(_Iter_pred<_Predicate> __pred) - { return _Iter_negate<_Predicate>(__pred._M_pred); } + { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } } // namespace __ops } // namespace __gnu_cxx diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 023f21efc7..797e7fcec3 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -1,6 +1,6 @@ // Pointer Traits -*- C++ -*- -// Copyright (C) 2011-2016 Free Software Foundation, Inc. +// Copyright (C) 2011-2017 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 @@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid. template<typename _Tp, typename _Up> struct __replace_first_arg - { using type = __undefined; }; + { }; template<template<typename, typename...> class _Template, typename _Up, typename _Tp, typename... _Types> @@ -84,8 +84,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __difference_type = typename _Tp::difference_type; + template<typename _Tp, typename _Up, typename = void> + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + template<typename _Tp, typename _Up> - using __rebind = typename _Tp::template rebind<_Up>; + struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>> + { using type = typename _Tp::template rebind<_Up>; }; public: /// The pointer type. @@ -93,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// The type pointed to. using element_type - = __detected_or_t_<__get_first_arg_t, __element_type, _Ptr>; + = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; /// The type used to represent the difference between two pointers. using difference_type @@ -101,8 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// A pointer to a different type. template<typename _Up> - using rebind - = __detected_or_t_<__replace_first_arg_t, __rebind, _Ptr, _Up>; + using rebind = typename __rebind<_Ptr, _Up>::type; static _Ptr pointer_to(__make_not_void<element_type>& __e) @@ -110,8 +113,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(!is_same<element_type, __undefined>::value, "pointer type defines element_type or is like SomePointer<T, Args>"); - static_assert(!is_same<rebind<element_type>, __undefined>::value, - "pointer type defines rebind<U> or is like SomePointer<T, Args>"); }; /** diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h index 1326d9fdf0..10cfec2118 100644 --- a/libstdc++-v3/include/bits/quoted_string.h +++ b/libstdc++-v3/include/bits/quoted_string.h @@ -1,6 +1,6 @@ // Helpers for quoted stream manipulators -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 9de480c021..d39cc3e066 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -1,6 +1,6 @@ // random number generation -*- C++ -*- -// Copyright (C) 2009-2016 Free Software Foundation, Inc. +// Copyright (C) 2009-2017 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 @@ -158,7 +158,7 @@ _GLIBCXX_END_NAMESPACE_VERSION struct _Adaptor { static_assert(std::is_floating_point<_DInputType>::value, - "template argument not a floating point type"); + "template argument must be a floating point type"); public: _Adaptor(_Engine& __g) @@ -235,8 +235,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _UIntType, _UIntType __a, _UIntType __c, _UIntType __m> class linear_congruential_engine { - static_assert(std::is_unsigned<_UIntType>::value, "template argument " - "substituting _UIntType not an unsigned integral type"); + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); static_assert(__m == 0u || (__a < __m && __c < __m), "template argument substituting __m out of bounds"); @@ -443,8 +443,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _UIntType __c, size_t __l, _UIntType __f> class mersenne_twister_engine { - static_assert(std::is_unsigned<_UIntType>::value, "template argument " - "substituting _UIntType not an unsigned integral type"); + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); static_assert(1u <= __m && __m <= __n, "template argument substituting __m out of bounds"); static_assert(__r <= __w, "template argument substituting " @@ -658,10 +658,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _UIntType, size_t __w, size_t __s, size_t __r> class subtract_with_carry_engine { - static_assert(std::is_unsigned<_UIntType>::value, "template argument " - "substituting _UIntType not an unsigned integral type"); + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); static_assert(0u < __s && __s < __r, - "template argument substituting __s out of bounds"); + "0 < s < r"); static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, "template argument substituting __w out of bounds"); @@ -1065,8 +1065,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _RandomNumberEngine, size_t __w, typename _UIntType> class independent_bits_engine { - static_assert(std::is_unsigned<_UIntType>::value, "template argument " - "substituting _UIntType not an unsigned integral type"); + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, "template argument substituting __w out of bounds"); @@ -1278,7 +1278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Produces random numbers by combining random numbers from some * base engine to produce random numbers with a specifies number of bits - * @p __w. + * @p __k. */ template<typename _RandomNumberEngine, size_t __k> class shuffle_order_engine @@ -1702,11 +1702,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class uniform_real_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -1732,6 +1733,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_a; _RealType _M_b; @@ -1920,11 +1925,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class normal_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -1951,6 +1957,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return (__p1._M_mean == __p2._M_mean && __p1._M_stddev == __p2._M_stddev); } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_mean; _RealType _M_stddev; @@ -2133,11 +2143,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class lognormal_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -2161,6 +2172,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_m == __p2._M_m && __p1._M_s == __p2._M_s; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_m; _RealType _M_s; @@ -2337,11 +2352,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class gamma_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -2370,6 +2386,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return (__p1._M_alpha == __p2._M_alpha && __p1._M_beta == __p2._M_beta); } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: void _M_initialize(); @@ -2554,11 +2574,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class chi_squared_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -2577,6 +2598,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_n == __p2._M_n; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_n; }; @@ -2764,11 +2789,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class cauchy_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -2792,6 +2818,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_a; _RealType _M_b; @@ -2965,11 +2995,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class fisher_f_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -2993,6 +3024,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_m == __p2._M_m && __p1._M_n == __p2._M_n; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_m; _RealType _M_n; @@ -3189,11 +3224,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class student_t_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -3212,6 +3248,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_n == __p2._M_n; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_n; }; @@ -3409,6 +3449,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: /** The type of the range of the distribution. */ typedef bool result_type; + /** Parameter type. */ struct param_type { @@ -3429,6 +3470,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_p == __p2._M_p; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: double _M_p; }; @@ -3612,11 +3657,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class binomial_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "result_type must be an integral type"); public: /** The type of the range of the distribution. */ typedef _IntType result_type; + /** Parameter type. */ struct param_type { @@ -3645,6 +3691,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_t == __p2._M_t && __p1._M_p == __p2._M_p; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: void _M_initialize(); @@ -3843,11 +3893,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class geometric_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "result_type must be an integral type"); public: /** The type of the range of the distribution. */ typedef _IntType result_type; + /** Parameter type. */ struct param_type { @@ -3870,6 +3921,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_p == __p2._M_p; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: void _M_initialize() @@ -4043,11 +4098,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class negative_binomial_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "result_type must be an integral type"); public: /** The type of the range of the distribution. */ typedef _IntType result_type; + /** Parameter type. */ struct param_type { @@ -4072,6 +4128,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_k == __p2._M_k && __p1._M_p == __p2._M_p; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _IntType _M_k; double _M_p; @@ -4265,11 +4325,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class poisson_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "result_type must be an integral type"); public: /** The type of the range of the distribution. */ typedef _IntType result_type; + /** Parameter type. */ struct param_type { @@ -4292,6 +4353,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_mean == __p2._M_mean; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: // Hosts either log(mean) or the threshold of the simple method. void @@ -4481,11 +4546,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class exponential_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -4506,6 +4572,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_lambda == __p2._M_lambda; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_lambda; }; @@ -4683,11 +4753,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class weibull_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -4711,6 +4782,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_a; _RealType _M_b; @@ -4886,11 +4961,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class extreme_value_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -4914,6 +4990,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _RealType _M_a; _RealType _M_b; @@ -5086,11 +5166,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class discrete_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "result_type must be an integral type"); public: /** The type of the range of the distribution. */ typedef _IntType result_type; + /** Parameter type. */ struct param_type { @@ -5127,6 +5208,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_prob == __p2._M_prob; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: void _M_initialize(); @@ -5316,11 +5401,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class piecewise_constant_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -5368,6 +5454,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: void _M_initialize(); @@ -5583,11 +5673,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class piecewise_linear_distribution { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "result_type must be a floating point type"); public: /** The type of the range of the distribution. */ typedef _RealType result_type; + /** Parameter type. */ struct param_type { @@ -5633,8 +5724,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend bool operator==(const param_type& __p1, const param_type& __p2) - { return (__p1._M_int == __p2._M_int - && __p1._M_den == __p2._M_den); } + { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } private: void diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 7dfc721e55..df05ebea6e 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -1,6 +1,6 @@ // random number generation (out of line) -*- C++ -*- -// Copyright (C) 2009-2016 Free Software Foundation, Inc. +// Copyright (C) 2009-2017 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 @@ -3312,7 +3312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION generate_canonical(_UniformRandomNumberGenerator& __urng) { static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); + "template argument must be a floating point type"); const size_t __b = std::min(static_cast<size_t>(std::numeric_limits<_RealType>::digits), @@ -3323,18 +3323,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const size_t __m = std::max<size_t>(1UL, (__b + __log2r - 1UL) / __log2r); _RealType __ret; - do + _RealType __sum = _RealType(0); + _RealType __tmp = _RealType(1); + for (size_t __k = __m; __k != 0; --__k) { - _RealType __sum = _RealType(0); - _RealType __tmp = _RealType(1); - for (size_t __k = __m; __k != 0; --__k) - { - __sum += _RealType(__urng() - __urng.min()) * __tmp; - __tmp *= __r; - } - __ret = __sum / __tmp; + __sum += _RealType(__urng() - __urng.min()) * __tmp; + __tmp *= __r; + } + __ret = __sum / __tmp; + if (__builtin_expect(__ret >= _RealType(1), 0)) + { +#if _GLIBCXX_USE_C99_MATH_TR1 + __ret = std::nextafter(_RealType(1), _RealType(0)); +#else + __ret = _RealType(1) + - std::numeric_limits<_RealType>::epsilon() / _RealType(2); +#endif } - while (__builtin_expect(__ret >= _RealType(1), 0)); return __ret; } diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h index e2ec072671..3987c2addf 100644 --- a/libstdc++-v3/include/bits/range_access.h +++ b/libstdc++-v3/include/bits/range_access.h @@ -1,6 +1,6 @@ // <range_access.h> -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -44,7 +44,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto begin(_Container& __cont) -> decltype(__cont.begin()) { return __cont.begin(); } @@ -54,7 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto begin(const _Container& __cont) -> decltype(__cont.begin()) { return __cont.begin(); } @@ -64,7 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto end(_Container& __cont) -> decltype(__cont.end()) { return __cont.end(); } @@ -74,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto end(const _Container& __cont) -> decltype(__cont.end()) { return __cont.end(); } @@ -134,7 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto rbegin(_Container& __cont) -> decltype(__cont.rbegin()) { return __cont.rbegin(); } @@ -144,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto rbegin(const _Container& __cont) -> decltype(__cont.rbegin()) { return __cont.rbegin(); } @@ -154,7 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto rend(_Container& __cont) -> decltype(__cont.rend()) { return __cont.rend(); } @@ -164,7 +164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto rend(const _Container& __cont) -> decltype(__cont.rend()) { return __cont.rend(); } @@ -174,7 +174,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __arr Array. */ template<typename _Tp, size_t _Nm> - inline reverse_iterator<_Tp*> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> rbegin(_Tp (&__arr)[_Nm]) { return reverse_iterator<_Tp*>(__arr + _Nm); } @@ -184,7 +184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __arr Array. */ template<typename _Tp, size_t _Nm> - inline reverse_iterator<_Tp*> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> rend(_Tp (&__arr)[_Nm]) { return reverse_iterator<_Tp*>(__arr); } @@ -194,7 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __il initializer_list. */ template<typename _Tp> - inline reverse_iterator<const _Tp*> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*> rbegin(initializer_list<_Tp> __il) { return reverse_iterator<const _Tp*>(__il.end()); } @@ -204,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __il initializer_list. */ template<typename _Tp> - inline reverse_iterator<const _Tp*> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*> rend(initializer_list<_Tp> __il) { return reverse_iterator<const _Tp*>(__il.begin()); } @@ -214,7 +214,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont)) { return std::rbegin(__cont); } @@ -224,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __cont Container. */ template<typename _Container> - inline auto + inline _GLIBCXX17_CONSTEXPR auto crend(const _Container& __cont) -> decltype(std::rend(__cont)) { return std::rend(__cont); } diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h new file mode 100644 index 0000000000..124ee97bd2 --- /dev/null +++ b/libstdc++-v3/include/bits/refwrap.h @@ -0,0 +1,383 @@ +// Implementation of std::reference_wrapper -*- C++ -*- + +// Copyright (C) 2004-2017 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 include/bits/bind.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_REFWRAP_H +#define _GLIBCXX_REFWRAP_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include <bits/c++0x_warning.h> +#else + +#include <bits/move.h> +#include <bits/invoke.h> +#include <bits/stl_function.h> // for unary_function and binary_function + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// If we have found a result_type, extract it. + template<typename _Functor, typename = __void_t<>> + struct _Maybe_get_result_type + { }; + + template<typename _Functor> + struct _Maybe_get_result_type<_Functor, + __void_t<typename _Functor::result_type>> + { typedef typename _Functor::result_type result_type; }; + + /** + * Base class for any function object that has a weak result type, as + * defined in 20.8.2 [func.require] of C++11. + */ + template<typename _Functor> + struct _Weak_result_type_impl + : _Maybe_get_result_type<_Functor> + { }; + + /// Retrieve the result type for a function type. + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes...)> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes......)> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes...) const> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes......) const> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes...) volatile> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes......) volatile> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes...) const volatile> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(_ArgTypes......) const volatile> + { typedef _Res result_type; }; + + /// Retrieve the result type for a function reference. + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(&)(_ArgTypes...)> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(&)(_ArgTypes......)> + { typedef _Res result_type; }; + + /// Retrieve the result type for a function pointer. + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(*)(_ArgTypes...)> + { typedef _Res result_type; }; + + template<typename _Res, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res(*)(_ArgTypes......)> + { typedef _Res result_type; }; + + /// Retrieve result type for a member function pointer. + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...)> + { typedef _Res result_type; }; + + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......)> + { typedef _Res result_type; }; + + /// Retrieve result type for a const member function pointer. + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) const> + { typedef _Res result_type; }; + + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) const> + { typedef _Res result_type; }; + + /// Retrieve result type for a volatile member function pointer. + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) volatile> + { typedef _Res result_type; }; + + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) volatile> + { typedef _Res result_type; }; + + /// Retrieve result type for a const volatile member function pointer. + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes...) + const volatile> + { typedef _Res result_type; }; + + template<typename _Res, typename _Class, typename... _ArgTypes> + struct _Weak_result_type_impl<_Res (_Class::*)(_ArgTypes......) + const volatile> + { typedef _Res result_type; }; + + /** + * Strip top-level cv-qualifiers from the function object and let + * _Weak_result_type_impl perform the real work. + */ + template<typename _Functor> + struct _Weak_result_type + : _Weak_result_type_impl<typename remove_cv<_Functor>::type> + { }; + + // Detect nested argument_type. + template<typename _Tp, typename = __void_t<>> + struct _Refwrap_base_arg1 + { }; + + // Nested argument_type. + template<typename _Tp> + struct _Refwrap_base_arg1<_Tp, + __void_t<typename _Tp::argument_type>> + { + typedef typename _Tp::argument_type argument_type; + }; + + // Detect nested first_argument_type and second_argument_type. + template<typename _Tp, typename = __void_t<>> + struct _Refwrap_base_arg2 + { }; + + // Nested first_argument_type and second_argument_type. + template<typename _Tp> + struct _Refwrap_base_arg2<_Tp, + __void_t<typename _Tp::first_argument_type, + typename _Tp::second_argument_type>> + { + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; + }; + + /** + * Derives from unary_function or binary_function when it + * can. Specializations handle all of the easy cases. The primary + * template determines what to do with a class type, which may + * derive from both unary_function and binary_function. + */ + template<typename _Tp> + struct _Reference_wrapper_base + : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> + { }; + + // - a function type (unary) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res(_T1)> + : unary_function<_T1, _Res> + { }; + + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res(_T1) const> + : unary_function<_T1, _Res> + { }; + + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res(_T1) volatile> + : unary_function<_T1, _Res> + { }; + + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res(_T1) const volatile> + : unary_function<_T1, _Res> + { }; + + // - a function type (binary) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res(_T1, _T2)> + : binary_function<_T1, _T2, _Res> + { }; + + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res(_T1, _T2) const> + : binary_function<_T1, _T2, _Res> + { }; + + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> + : binary_function<_T1, _T2, _Res> + { }; + + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> + : binary_function<_T1, _T2, _Res> + { }; + + // - a function pointer type (unary) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res(*)(_T1)> + : unary_function<_T1, _Res> + { }; + + // - a function pointer type (binary) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res(*)(_T1, _T2)> + : binary_function<_T1, _T2, _Res> + { }; + + // - a pointer to member function type (unary, no qualifiers) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res (_T1::*)()> + : unary_function<_T1*, _Res> + { }; + + // - a pointer to member function type (binary, no qualifiers) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res (_T1::*)(_T2)> + : binary_function<_T1*, _T2, _Res> + { }; + + // - a pointer to member function type (unary, const) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res (_T1::*)() const> + : unary_function<const _T1*, _Res> + { }; + + // - a pointer to member function type (binary, const) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const> + : binary_function<const _T1*, _T2, _Res> + { }; + + // - a pointer to member function type (unary, volatile) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res (_T1::*)() volatile> + : unary_function<volatile _T1*, _Res> + { }; + + // - a pointer to member function type (binary, volatile) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res (_T1::*)(_T2) volatile> + : binary_function<volatile _T1*, _T2, _Res> + { }; + + // - a pointer to member function type (unary, const volatile) + template<typename _Res, typename _T1> + struct _Reference_wrapper_base<_Res (_T1::*)() const volatile> + : unary_function<const volatile _T1*, _Res> + { }; + + // - a pointer to member function type (binary, const volatile) + template<typename _Res, typename _T1, typename _T2> + struct _Reference_wrapper_base<_Res (_T1::*)(_T2) const volatile> + : binary_function<const volatile _T1*, _T2, _Res> + { }; + + /** + * @brief Primary class template for reference_wrapper. + * @ingroup functors + * @{ + */ + template<typename _Tp> + class reference_wrapper + : public _Reference_wrapper_base<typename remove_cv<_Tp>::type> + { + _Tp* _M_data; + + public: + typedef _Tp type; + + reference_wrapper(_Tp& __indata) noexcept + : _M_data(std::__addressof(__indata)) + { } + + reference_wrapper(_Tp&&) = delete; + + reference_wrapper(const reference_wrapper&) = default; + + reference_wrapper& + operator=(const reference_wrapper&) = default; + + operator _Tp&() const noexcept + { return this->get(); } + + _Tp& + get() const noexcept + { return *_M_data; } + + template<typename... _Args> + typename result_of<_Tp&(_Args&&...)>::type + operator()(_Args&&... __args) const + { + return std::__invoke(get(), std::forward<_Args>(__args)...); + } + }; + + + /// Denotes a reference should be taken to a variable. + template<typename _Tp> + inline reference_wrapper<_Tp> + ref(_Tp& __t) noexcept + { return reference_wrapper<_Tp>(__t); } + + /// Denotes a const reference should be taken to a variable. + template<typename _Tp> + inline reference_wrapper<const _Tp> + cref(const _Tp& __t) noexcept + { return reference_wrapper<const _Tp>(__t); } + + template<typename _Tp> + void ref(const _Tp&&) = delete; + + template<typename _Tp> + void cref(const _Tp&&) = delete; + + /// Partial specialization. + template<typename _Tp> + inline reference_wrapper<_Tp> + ref(reference_wrapper<_Tp> __t) noexcept + { return ref(__t.get()); } + + /// Partial specialization. + template<typename _Tp> + inline reference_wrapper<const _Tp> + cref(reference_wrapper<_Tp> __t) noexcept + { return cref(__t.get()); } + + // @} group functors + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_REFWRAP_H diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h index 4e87bc0088..60837ea6cf 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -762,17 +762,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _FwdIter> basic_regex(_FwdIter __first, _FwdIter __last, locale_type __loc, flag_type __f) - : _M_flags(__f), _M_loc(std::move(__loc)), + : _M_flags((__f & (ECMAScript | basic | extended | awk | grep | egrep)) + ? __f : (__f | ECMAScript)), + _M_loc(std::move(__loc)), _M_automaton(__detail::__compile_nfa<_FwdIter, _Rx_traits>( std::move(__first), std::move(__last), _M_loc, _M_flags)) { } template<typename _Bp, typename _Ap, typename _Cp, typename _Rp, __detail::_RegexExecutorPolicy, bool> - friend bool - __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&, - const basic_regex<_Cp, _Rp>&, - regex_constants::match_flag_type); + friend bool __detail:: +#if _GLIBCXX_INLINE_VERSION + __7:: // Required due to PR c++/59256 +#endif + __regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&, + const basic_regex<_Cp, _Rp>&, + regex_constants::match_flag_type); template<typename, typename, typename, bool> friend class __detail::_Executor; @@ -1860,10 +1865,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template<typename _Bp, typename _Ap, typename _Cp, typename _Rp, __detail::_RegexExecutorPolicy, bool> - friend bool - __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&, - const basic_regex<_Cp, _Rp>&, - regex_constants::match_flag_type); + friend bool __detail:: +#if _GLIBCXX_INLINE_VERSION + __7:: // Required due to PR c++/59256 +#endif + __regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&, + const basic_regex<_Cp, _Rp>&, + regex_constants::match_flag_type); void _M_resize(unsigned int __size) @@ -2448,7 +2456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * one-past-the-end of a range. */ regex_iterator() - : _M_match() + : _M_pregex() { } /** @@ -2666,9 +2674,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 initializer_list<int>, regex_constants::match_flag_type = regex_constants::match_default) = delete; - template <std::size_t N> + template <std::size_t _Nm> regex_token_iterator(_Bi_iter, _Bi_iter, const regex_type&&, - const int (&)[N], + const int (&)[_Nm], regex_constants::match_flag_type = regex_constants::match_default) = delete; diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc index 4a3d7c36cf..dc32a49dcd 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -496,12 +496,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>:: operator==(const regex_iterator& __rhs) const { - return (_M_match.empty() && __rhs._M_match.empty()) - || (_M_begin == __rhs._M_begin - && _M_end == __rhs._M_end - && _M_pregex == __rhs._M_pregex - && _M_flags == __rhs._M_flags - && _M_match[0] == __rhs._M_match[0]); + if (_M_pregex == nullptr && __rhs._M_pregex == nullptr) + return true; + return _M_pregex == __rhs._M_pregex + && _M_begin == __rhs._M_begin + && _M_end == __rhs._M_end + && _M_flags == __rhs._M_flags + && _M_match[0] == __rhs._M_match[0]; } template<typename _Bi_iter, @@ -525,7 +526,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__start == _M_end) { - _M_match = value_type(); + _M_pregex = nullptr; return *this; } else @@ -558,7 +559,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_match._M_begin = _M_begin; } else - _M_match = value_type(); + _M_pregex = nullptr; } return *this; } diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h index 07158c4926..a5fab6356c 100644 --- a/libstdc++-v3/include/bits/regex_automaton.h +++ b/libstdc++-v3/include/bits/regex_automaton.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -241,7 +241,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _StateIdT - _M_insert_alt(_StateIdT __next, _StateIdT __alt, bool __neg) + _M_insert_alt(_StateIdT __next, _StateIdT __alt, + bool __neg __attribute__((__unused__))) { _StateT __tmp(_S_opcode_alternative); // It labels every quantifier to make greedy comparison easier in BFS diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc index 6955ab9203..727bde1f6c 100644 --- a/libstdc++-v3/include/bits/regex_automaton.tcc +++ b/libstdc++-v3/include/bits/regex_automaton.tcc @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index 410d61b7da..49c01840c9 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -30,6 +30,15 @@ namespace std _GLIBCXX_VISIBILITY(default) { +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + template<typename> + class regex_traits; + +_GLIBCXX_END_NAMESPACE_CXX11 +_GLIBCXX_END_NAMESPACE_VERSION + namespace __detail { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -207,17 +216,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [28.13.14] template<typename _TraitsT, bool __icase, bool __collate> - class _RegexTranslator + class _RegexTranslatorBase { public: typedef typename _TraitsT::char_type _CharT; typedef typename _TraitsT::string_type _StringT; - typedef typename std::conditional<__collate, - _StringT, - _CharT>::type _StrTransT; + typedef _StringT _StrTransT; explicit - _RegexTranslator(const _TraitsT& __traits) + _RegexTranslatorBase(const _TraitsT& __traits) : _M_traits(__traits) { } @@ -235,23 +242,86 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _StrTransT _M_transform(_CharT __ch) const { - return _M_transform_impl(__ch, typename integral_constant<bool, - __collate>::type()); + _StrTransT __str(1, __ch); + return _M_traits.transform(__str.begin(), __str.end()); } - private: + // See LWG 523. It's not efficiently implementable when _TraitsT is not + // std::regex_traits<>, and __collate is true. See specializations for + // implementations of other cases. + bool + _M_match_range(const _StrTransT& __first, const _StrTransT& __last, + const _StrTransT& __s) const + { return __first <= __s && __s <= __last; } + + protected: + bool _M_in_range_icase(_CharT __first, _CharT __last, _CharT __ch) const + { + typedef std::ctype<_CharT> __ctype_type; + const auto& __fctyp = use_facet<__ctype_type>(this->_M_traits.getloc()); + auto __lower = __fctyp.tolower(__ch); + auto __upper = __fctyp.toupper(__ch); + return (__first <= __lower && __lower <= __last) + || (__first <= __upper && __upper <= __last); + } + + const _TraitsT& _M_traits; + }; + + template<typename _TraitsT, bool __icase, bool __collate> + class _RegexTranslator + : public _RegexTranslatorBase<_TraitsT, __icase, __collate> + { + public: + typedef _RegexTranslatorBase<_TraitsT, __icase, __collate> _Base; + using _Base::_Base; + }; + + template<typename _TraitsT, bool __icase> + class _RegexTranslator<_TraitsT, __icase, false> + : public _RegexTranslatorBase<_TraitsT, __icase, false> + { + public: + typedef _RegexTranslatorBase<_TraitsT, __icase, false> _Base; + typedef typename _Base::_CharT _CharT; + typedef _CharT _StrTransT; + + using _Base::_Base; + _StrTransT - _M_transform_impl(_CharT __ch, false_type) const + _M_transform(_CharT __ch) const { return __ch; } - _StrTransT - _M_transform_impl(_CharT __ch, true_type) const + bool + _M_match_range(_CharT __first, _CharT __last, _CharT __ch) const { - _StrTransT __str = _StrTransT(1, _M_translate(__ch)); - return _M_traits.transform(__str.begin(), __str.end()); + if (!__icase) + return __first <= __ch && __ch <= __last; + return this->_M_in_range_icase(__first, __last, __ch); } + }; - const _TraitsT& _M_traits; + template<typename _CharType> + class _RegexTranslator<std::regex_traits<_CharType>, true, true> + : public _RegexTranslatorBase<std::regex_traits<_CharType>, true, true> + { + public: + typedef _RegexTranslatorBase<std::regex_traits<_CharType>, true, true> + _Base; + typedef typename _Base::_CharT _CharT; + typedef typename _Base::_StrTransT _StrTransT; + + using _Base::_Base; + + bool + _M_match_range(const _StrTransT& __first, const _StrTransT& __last, + const _StrTransT& __str) const + { + __glibcxx_assert(__first.size() == 1); + __glibcxx_assert(__last.size() == 1); + __glibcxx_assert(__str.size() == 1); + return this->_M_in_range_icase(__first[0], __last[0], __str[0]); + } }; template<typename _TraitsT> @@ -272,6 +342,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _StrTransT _M_transform(_CharT __ch) const { return __ch; } + + bool + _M_match_range(_CharT __first, _CharT __last, _CharT __ch) const + { return __first <= __ch && __ch <= __last; } }; template<typename _TraitsT, bool __is_ecma, bool __icase, bool __collate> diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc index ff69e16551..a6d8016d87 100644 --- a/libstdc++-v3/include/bits/regex_compiler.tcc +++ b/libstdc++-v3/include/bits/regex_compiler.tcc @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -426,13 +426,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pair<bool, _CharT> __last_char; // Optional<_CharT> __last_char.first = false; if (!(_M_flags & regex_constants::ECMAScript)) - if (_M_try_char()) - { - __matcher._M_add_char(_M_value[0]); - __last_char.first = true; - __last_char.second = _M_value[0]; - } + { + if (_M_try_char()) + { + __last_char.first = true; + __last_char.second = _M_value[0]; + } + else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) + { + __last_char.first = true; + __last_char.second = '-'; + } + } while (_M_expression_term(__last_char, __matcher)); + if (__last_char.first) + __matcher._M_add_char(__last_char.second); __matcher._M_ready(); _M_stack.push(_StateSeqT( *_M_nfa, @@ -449,19 +457,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_match_token(_ScannerT::_S_token_bracket_end)) return false; + const auto __push_char = [&](_CharT __ch) + { + if (__last_char.first) + __matcher._M_add_char(__last_char.second); + else + __last_char.first = true; + __last_char.second = __ch; + }; + const auto __flush = [&] + { + if (__last_char.first) + { + __matcher._M_add_char(__last_char.second); + __last_char.first = false; + } + }; + if (_M_match_token(_ScannerT::_S_token_collsymbol)) { auto __symbol = __matcher._M_add_collate_element(_M_value); if (__symbol.size() == 1) - { - __last_char.first = true; - __last_char.second = __symbol[0]; - } + __push_char(__symbol[0]); + else + __flush(); } else if (_M_match_token(_ScannerT::_S_token_equiv_class_name)) - __matcher._M_add_equivalence_class(_M_value); + { + __flush(); + __matcher._M_add_equivalence_class(_M_value); + } else if (_M_match_token(_ScannerT::_S_token_char_class_name)) - __matcher._M_add_character_class(_M_value, false); + { + __flush(); + __matcher._M_add_character_class(_M_value, false); + } + else if (_M_try_char()) + __push_char(_M_value[0]); // POSIX doesn't allow '-' as a start-range char (say [a-z--0]), // except when the '-' is the first or last character in the bracket // expression ([--0]). ECMAScript treats all '-' after a range as a @@ -472,55 +504,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Clang (3.5) always uses ECMAScript style even in its POSIX syntax. // // It turns out that no one reads BNFs ;) - else if (_M_try_char()) + else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) { if (!__last_char.first) { - __matcher._M_add_char(_M_value[0]); - if (_M_value[0] == '-' - && !(_M_flags & regex_constants::ECMAScript)) + if (!(_M_flags & regex_constants::ECMAScript)) { if (_M_match_token(_ScannerT::_S_token_bracket_end)) - return false; + { + __push_char('-'); + return false; + } __throw_regex_error( regex_constants::error_range, "Unexpected dash in bracket expression. For POSIX syntax, " "a dash is not treated literally only when it is at " "beginning or end."); } - __last_char.first = true; - __last_char.second = _M_value[0]; + __push_char('-'); } else { - if (_M_value[0] == '-') + if (_M_try_char()) { - if (_M_try_char()) - { - __matcher._M_make_range(__last_char.second , _M_value[0]); - __last_char.first = false; - } - else - { - if (_M_scanner._M_get_token() - != _ScannerT::_S_token_bracket_end) - __throw_regex_error( - regex_constants::error_range, - "Unexpected end of bracket expression."); - __matcher._M_add_char(_M_value[0]); - } + __matcher._M_make_range(__last_char.second, _M_value[0]); + __last_char.first = false; + } + else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) + { + __matcher._M_make_range(__last_char.second, '-'); + __last_char.first = false; } else { - __matcher._M_add_char(_M_value[0]); - __last_char.second = _M_value[0]; + if (_M_scanner._M_get_token() + != _ScannerT::_S_token_bracket_end) + __throw_regex_error( + regex_constants::error_range, + "Character is expected after a dash."); + __push_char('-'); } } } else if (_M_match_token(_ScannerT::_S_token_quoted_class)) - __matcher._M_add_character_class(_M_value, - _M_ctype.is(_CtypeT::upper, - _M_value[0])); + { + __flush(); + __matcher._M_add_character_class(_M_value, + _M_ctype.is(_CtypeT::upper, + _M_value[0])); + } else __throw_regex_error(regex_constants::error_brack, "Unexpected character in bracket expression."); @@ -580,37 +612,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _BracketMatcher<_TraitsT, __icase, __collate>:: _M_apply(_CharT __ch, false_type) const { - bool __ret = std::binary_search(_M_char_set.begin(), _M_char_set.end(), - _M_translator._M_translate(__ch)); - if (!__ret) - { - auto __s = _M_translator._M_transform(__ch); - for (auto& __it : _M_range_set) - if (__it.first <= __s && __s <= __it.second) - { - __ret = true; - break; - } - if (_M_traits.isctype(__ch, _M_class_set)) - __ret = true; - else if (std::find(_M_equiv_set.begin(), _M_equiv_set.end(), - _M_traits.transform_primary(&__ch, &__ch+1)) - != _M_equiv_set.end()) - __ret = true; - else - { - for (auto& __it : _M_neg_class_set) - if (!_M_traits.isctype(__ch, __it)) - { - __ret = true; - break; - } - } - } - if (_M_is_non_matching) - return !__ret; - else - return __ret; + return [this, __ch] + { + if (std::binary_search(_M_char_set.begin(), _M_char_set.end(), + _M_translator._M_translate(__ch))) + return true; + auto __s = _M_translator._M_transform(__ch); + for (auto& __it : _M_range_set) + if (_M_translator._M_match_range(__it.first, __it.second, __s)) + return true; + if (_M_traits.isctype(__ch, _M_class_set)) + return true; + if (std::find(_M_equiv_set.begin(), _M_equiv_set.end(), + _M_traits.transform_primary(&__ch, &__ch+1)) + != _M_equiv_set.end()) + return true; + for (auto& __it : _M_neg_class_set) + if (!_M_traits.isctype(__ch, __it)) + return true; + return false; + }() ^ _M_is_non_matching; } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/regex_constants.h b/libstdc++-v3/include/bits/regex_constants.h index 4b063cc2a7..dad2d637aa 100644 --- a/libstdc++-v3/include/bits/regex_constants.h +++ b/libstdc++-v3/include/bits/regex_constants.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Specifies that the matching of regular expressions against a character * sequence shall be performed without regard to case. */ - constexpr syntax_option_type icase = + _GLIBCXX17_INLINE constexpr syntax_option_type icase = static_cast<syntax_option_type>(1 << _S_icase); /** @@ -92,7 +92,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * container sequence, no sub-expression matches are to be stored in the * supplied match_results structure. */ - constexpr syntax_option_type nosubs = + _GLIBCXX17_INLINE constexpr syntax_option_type nosubs = static_cast<syntax_option_type>(1 << _S_nosubs); /** @@ -101,14 +101,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * speed with which regular expression objects are constructed. Otherwise * it has no detectable effect on the program output. */ - constexpr syntax_option_type optimize = + _GLIBCXX17_INLINE constexpr syntax_option_type optimize = static_cast<syntax_option_type>(1 << _S_optimize); /** * Specifies that character ranges of the form [a-b] should be locale * sensitive. */ - constexpr syntax_option_type collate = + _GLIBCXX17_INLINE constexpr syntax_option_type collate = static_cast<syntax_option_type>(1 << _S_collate); /** @@ -119,7 +119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * in the PERL scripting language but extended with elements found in the * POSIX regular expression grammar. */ - constexpr syntax_option_type ECMAScript = + _GLIBCXX17_INLINE constexpr syntax_option_type ECMAScript = static_cast<syntax_option_type>(1 << _S_ECMAScript); /** @@ -129,7 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Headers, Section 9, Regular Expressions [IEEE, Information Technology -- * Portable Operating System Interface (POSIX), IEEE Standard 1003.1-2001]. */ - constexpr syntax_option_type basic = + _GLIBCXX17_INLINE constexpr syntax_option_type basic = static_cast<syntax_option_type>(1 << _S_basic); /** @@ -138,7 +138,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Portable Operating System Interface (POSIX), Base Definitions and * Headers, Section 9, Regular Expressions. */ - constexpr syntax_option_type extended = + _GLIBCXX17_INLINE constexpr syntax_option_type extended = static_cast<syntax_option_type>(1 << _S_extended); /** @@ -149,7 +149,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * \\\\, \\a, \\b, \\f, \\n, \\r, \\t , \\v, \\&apos,, &apos,, * and \\ddd (where ddd is one, two, or three octal digits). */ - constexpr syntax_option_type awk = + _GLIBCXX17_INLINE constexpr syntax_option_type awk = static_cast<syntax_option_type>(1 << _S_awk); /** @@ -158,7 +158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * identical to syntax_option_type basic, except that newlines are treated * as whitespace. */ - constexpr syntax_option_type grep = + _GLIBCXX17_INLINE constexpr syntax_option_type grep = static_cast<syntax_option_type>(1 << _S_grep); /** @@ -167,7 +167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * IEEE Std 1003.1-2001. This option is identical to syntax_option_type * extended, except that newlines are treated as whitespace. */ - constexpr syntax_option_type egrep = + _GLIBCXX17_INLINE constexpr syntax_option_type egrep = static_cast<syntax_option_type>(1 << _S_egrep); /** @@ -176,7 +176,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * If specified in a regex with back-references, the exception * regex_constants::error_complexity will be thrown. */ - constexpr syntax_option_type __polynomial = + _GLIBCXX17_INLINE constexpr syntax_option_type __polynomial = static_cast<syntax_option_type>(1 << _S_polynomial); constexpr inline syntax_option_type @@ -257,14 +257,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * The default matching rules. */ - constexpr match_flag_type match_default = static_cast<match_flag_type>(0); + _GLIBCXX17_INLINE constexpr match_flag_type match_default = + static_cast<match_flag_type>(0); /** * The first character in the sequence [first, last) is treated as though it * is not at the beginning of a line, so the character (^) in the regular * expression shall not match [first, first). */ - constexpr match_flag_type match_not_bol = + _GLIBCXX17_INLINE constexpr match_flag_type match_not_bol = static_cast<match_flag_type>(1 << _S_not_bol); /** @@ -272,40 +273,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * is not at the end of a line, so the character ($) in the regular * expression shall not match [last, last). */ - constexpr match_flag_type match_not_eol = + _GLIBCXX17_INLINE constexpr match_flag_type match_not_eol = static_cast<match_flag_type>(1 << _S_not_eol); /** * The expression \\b is not matched against the sub-sequence * [first,first). */ - constexpr match_flag_type match_not_bow = + _GLIBCXX17_INLINE constexpr match_flag_type match_not_bow = static_cast<match_flag_type>(1 << _S_not_bow); /** * The expression \\b should not be matched against the sub-sequence * [last,last). */ - constexpr match_flag_type match_not_eow = + _GLIBCXX17_INLINE constexpr match_flag_type match_not_eow = static_cast<match_flag_type>(1 << _S_not_eow); /** * If more than one match is possible then any match is an acceptable * result. */ - constexpr match_flag_type match_any = + _GLIBCXX17_INLINE constexpr match_flag_type match_any = static_cast<match_flag_type>(1 << _S_any); /** * The expression does not match an empty sequence. */ - constexpr match_flag_type match_not_null = + _GLIBCXX17_INLINE constexpr match_flag_type match_not_null = static_cast<match_flag_type>(1 << _S_not_null); /** * The expression only matches a sub-sequence that begins at first . */ - constexpr match_flag_type match_continuous = + _GLIBCXX17_INLINE constexpr match_flag_type match_continuous = static_cast<match_flag_type>(1 << _S_continuous); /** @@ -313,7 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * flags match_not_bol and match_not_bow are ignored by the regular * expression algorithms 28.11 and iterators 28.12. */ - constexpr match_flag_type match_prev_avail = + _GLIBCXX17_INLINE constexpr match_flag_type match_prev_avail = static_cast<match_flag_type>(1 << _S_prev_avail); /** @@ -342,7 +343,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * undefined, use the empty string instead. If * nn > match_results::size(), the result is implementation-defined. */ - constexpr match_flag_type format_default = static_cast<match_flag_type>(0); + _GLIBCXX17_INLINE constexpr match_flag_type format_default = + static_cast<match_flag_type>(0); /** * When a regular expression match is to be replaced by a new string, the @@ -350,7 +352,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * in IEEE Std 1003.1- 2001 [IEEE, Information Technology -- Portable * Operating System Interface (POSIX), IEEE Standard 1003.1-2001]. */ - constexpr match_flag_type format_sed = + _GLIBCXX17_INLINE constexpr match_flag_type format_sed = static_cast<match_flag_type>(1 << _S_sed); /** @@ -358,14 +360,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * container sequence being searched that do not match the regular * expression shall not be copied to the output string. */ - constexpr match_flag_type format_no_copy = + _GLIBCXX17_INLINE constexpr match_flag_type format_no_copy = static_cast<match_flag_type>(1 << _S_no_copy); /** * When specified during a search and replace operation, only the first * occurrence of the regular expression shall be replaced. */ - constexpr match_flag_type format_first_only = + _GLIBCXX17_INLINE constexpr match_flag_type format_first_only = static_cast<match_flag_type>(1 << _S_first_only); constexpr inline match_flag_type diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h index 16bf78c5e3..55f6db9cf7 100644 --- a/libstdc++-v3/include/bits/regex_error.h +++ b/libstdc++-v3/include/bits/regex_error.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h index ef8aa9167d..6105474287 100644 --- a/libstdc++-v3/include/bits/regex_executor.h +++ b/libstdc++-v3/include/bits/regex_executor.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -109,6 +109,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_rep_once_more(_Match_mode __match_mode, _StateIdT); void + _M_handle_repeat(_Match_mode, _StateIdT); + + void + _M_handle_subexpr_begin(_Match_mode, _StateIdT); + + void + _M_handle_subexpr_end(_Match_mode, _StateIdT); + + void + _M_handle_line_begin_assertion(_Match_mode, _StateIdT); + + void + _M_handle_line_end_assertion(_Match_mode, _StateIdT); + + void + _M_handle_word_boundary(_Match_mode, _StateIdT); + + void + _M_handle_subexpr_lookahead(_Match_mode, _StateIdT); + + void + _M_handle_match(_Match_mode, _StateIdT); + + void + _M_handle_backref(_Match_mode, _StateIdT); + + void + _M_handle_accept(_Match_mode, _StateIdT); + + void + _M_handle_alternative(_Match_mode, _StateIdT); + + void _M_dfs(_Match_mode __match_mode, _StateIdT __start); bool diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc index 2abd02099d..9d4ece7441 100644 --- a/libstdc++-v3/include/bits/regex_executor.tcc +++ b/libstdc++-v3/include/bits/regex_executor.tcc @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -195,213 +195,295 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + // _M_alt branch is "match once more", while _M_next is "get me out + // of this quantifier". Executing _M_next first or _M_alt first don't + // mean the same thing, and we need to choose the correct order under + // given greedy mode. template<typename _BiIter, typename _Alloc, typename _TraitsT, bool __dfs_mode> void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: - _M_dfs(_Match_mode __match_mode, _StateIdT __i) + _M_handle_repeat(_Match_mode __match_mode, _StateIdT __i) { - if (_M_states._M_visited(__i)) - return; - const auto& __state = _M_nfa[__i]; - // Every change on _M_cur_results and _M_current will be rolled back after - // finishing the recursion step. - switch (__state._M_opcode()) + + // Greedy. + if (!__state._M_neg) { - // _M_alt branch is "match once more", while _M_next is "get me out - // of this quantifier". Executing _M_next first or _M_alt first don't - // mean the same thing, and we need to choose the correct order under - // given greedy mode. - case _S_opcode_repeat: - { - // Greedy. - if (!__state._M_neg) - { - _M_rep_once_more(__match_mode, __i); - // If it's DFS executor and already accepted, we're done. - if (!__dfs_mode || !_M_has_sol) - _M_dfs(__match_mode, __state._M_next); - } - else // Non-greedy mode - { - if (__dfs_mode) - { - // vice-versa. - _M_dfs(__match_mode, __state._M_next); - if (!_M_has_sol) - _M_rep_once_more(__match_mode, __i); - } - else - { - // DON'T attempt anything, because there's already another - // state with higher priority accepted. This state cannot - // be better by attempting its next node. - if (!_M_has_sol) - { - _M_dfs(__match_mode, __state._M_next); - // DON'T attempt anything if it's already accepted. An - // accepted state *must* be better than a solution that - // matches a non-greedy quantifier one more time. - if (!_M_has_sol) - _M_rep_once_more(__match_mode, __i); - } - } - } - } - break; - case _S_opcode_subexpr_begin: - { - auto& __res = _M_cur_results[__state._M_subexpr]; - auto __back = __res.first; - __res.first = _M_current; - _M_dfs(__match_mode, __state._M_next); - __res.first = __back; - } - break; - case _S_opcode_subexpr_end: - { - auto& __res = _M_cur_results[__state._M_subexpr]; - auto __back = __res; - __res.second = _M_current; - __res.matched = true; - _M_dfs(__match_mode, __state._M_next); - __res = __back; - } - break; - case _S_opcode_line_begin_assertion: - if (_M_at_begin()) - _M_dfs(__match_mode, __state._M_next); - break; - case _S_opcode_line_end_assertion: - if (_M_at_end()) - _M_dfs(__match_mode, __state._M_next); - break; - case _S_opcode_word_boundary: - if (_M_word_boundary() == !__state._M_neg) - _M_dfs(__match_mode, __state._M_next); - break; - // Here __state._M_alt offers a single start node for a sub-NFA. - // We recursively invoke our algorithm to match the sub-NFA. - case _S_opcode_subexpr_lookahead: - if (_M_lookahead(__state._M_alt) == !__state._M_neg) + _M_rep_once_more(__match_mode, __i); + // If it's DFS executor and already accepted, we're done. + if (!__dfs_mode || !_M_has_sol) _M_dfs(__match_mode, __state._M_next); - break; - case _S_opcode_match: - if (_M_current == _M_end) - break; + } + else // Non-greedy mode + { if (__dfs_mode) { - if (__state._M_matches(*_M_current)) - { - ++_M_current; - _M_dfs(__match_mode, __state._M_next); - --_M_current; - } + // vice-versa. + _M_dfs(__match_mode, __state._M_next); + if (!_M_has_sol) + _M_rep_once_more(__match_mode, __i); } else - if (__state._M_matches(*_M_current)) - _M_states._M_queue(__state._M_next, _M_cur_results); - break; - // First fetch the matched result from _M_cur_results as __submatch; - // then compare it with - // (_M_current, _M_current + (__submatch.second - __submatch.first)). - // If matched, keep going; else just return and try another state. - case _S_opcode_backref: - { - __glibcxx_assert(__dfs_mode); - auto& __submatch = _M_cur_results[__state._M_backref_index]; - if (!__submatch.matched) - break; - auto __last = _M_current; - for (auto __tmp = __submatch.first; - __last != _M_end && __tmp != __submatch.second; - ++__tmp) - ++__last; - if (_M_re._M_automaton->_M_traits.transform(__submatch.first, - __submatch.second) - == _M_re._M_automaton->_M_traits.transform(_M_current, __last)) - { - if (__last != _M_current) - { - auto __backup = _M_current; - _M_current = __last; - _M_dfs(__match_mode, __state._M_next); - _M_current = __backup; - } - else - _M_dfs(__match_mode, __state._M_next); - } - } - break; - case _S_opcode_accept: - if (__dfs_mode) { - __glibcxx_assert(!_M_has_sol); - if (__match_mode == _Match_mode::_Exact) - _M_has_sol = _M_current == _M_end; - else - _M_has_sol = true; - if (_M_current == _M_begin - && (_M_flags & regex_constants::match_not_null)) - _M_has_sol = false; - if (_M_has_sol) + // DON'T attempt anything, because there's already another + // state with higher priority accepted. This state cannot + // be better by attempting its next node. + if (!_M_has_sol) { - if (_M_nfa._M_flags & regex_constants::ECMAScript) - _M_results = _M_cur_results; - else // POSIX - { - __glibcxx_assert(_M_states._M_get_sol_pos()); - // Here's POSIX's logic: match the longest one. However - // we never know which one (lhs or rhs of "|") is longer - // unless we try both of them and compare the results. - // The member variable _M_sol_pos records the end - // position of the last successful match. It's better - // to be larger, because POSIX regex is always greedy. - // TODO: This could be slow. - if (*_M_states._M_get_sol_pos() == _BiIter() - || std::distance(_M_begin, - *_M_states._M_get_sol_pos()) - < std::distance(_M_begin, _M_current)) - { - *_M_states._M_get_sol_pos() = _M_current; - _M_results = _M_cur_results; - } - } + _M_dfs(__match_mode, __state._M_next); + // DON'T attempt anything if it's already accepted. An + // accepted state *must* be better than a solution that + // matches a non-greedy quantifier one more time. + if (!_M_has_sol) + _M_rep_once_more(__match_mode, __i); } } - else + } + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_subexpr_begin(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + + auto& __res = _M_cur_results[__state._M_subexpr]; + auto __back = __res.first; + __res.first = _M_current; + _M_dfs(__match_mode, __state._M_next); + __res.first = __back; + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_subexpr_end(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + + auto& __res = _M_cur_results[__state._M_subexpr]; + auto __back = __res; + __res.second = _M_current; + __res.matched = true; + _M_dfs(__match_mode, __state._M_next); + __res = __back; + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_line_begin_assertion(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + if (_M_at_begin()) + _M_dfs(__match_mode, __state._M_next); + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_line_end_assertion(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + if (_M_at_end()) + _M_dfs(__match_mode, __state._M_next); + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_word_boundary(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + if (_M_word_boundary() == !__state._M_neg) + _M_dfs(__match_mode, __state._M_next); + } + + // Here __state._M_alt offers a single start node for a sub-NFA. + // We recursively invoke our algorithm to match the sub-NFA. + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_subexpr_lookahead(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + if (_M_lookahead(__state._M_alt) == !__state._M_neg) + _M_dfs(__match_mode, __state._M_next); + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_match(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + + if (_M_current == _M_end) + return; + if (__dfs_mode) + { + if (__state._M_matches(*_M_current)) { - if (_M_current == _M_begin - && (_M_flags & regex_constants::match_not_null)) - break; - if (__match_mode == _Match_mode::_Prefix || _M_current == _M_end) - if (!_M_has_sol) - { - _M_has_sol = true; - _M_results = _M_cur_results; - } + ++_M_current; + _M_dfs(__match_mode, __state._M_next); + --_M_current; } - break; - case _S_opcode_alternative: - if (_M_nfa._M_flags & regex_constants::ECMAScript) + } + else + if (__state._M_matches(*_M_current)) + _M_states._M_queue(__state._M_next, _M_cur_results); + } + + // First fetch the matched result from _M_cur_results as __submatch; + // then compare it with + // (_M_current, _M_current + (__submatch.second - __submatch.first)). + // If matched, keep going; else just return and try another state. + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_backref(_Match_mode __match_mode, _StateIdT __i) + { + __glibcxx_assert(__dfs_mode); + + const auto& __state = _M_nfa[__i]; + auto& __submatch = _M_cur_results[__state._M_backref_index]; + if (!__submatch.matched) + return; + auto __last = _M_current; + for (auto __tmp = __submatch.first; + __last != _M_end && __tmp != __submatch.second; + ++__tmp) + ++__last; + if (_M_re._M_automaton->_M_traits.transform(__submatch.first, + __submatch.second) + == _M_re._M_automaton->_M_traits.transform(_M_current, __last)) + { + if (__last != _M_current) { - // TODO: Fix BFS support. It is wrong. - _M_dfs(__match_mode, __state._M_alt); - // Pick lhs if it matches. Only try rhs if it doesn't. - if (!_M_has_sol) - _M_dfs(__match_mode, __state._M_next); + auto __backup = _M_current; + _M_current = __last; + _M_dfs(__match_mode, __state._M_next); + _M_current = __backup; } else + _M_dfs(__match_mode, __state._M_next); + } + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_accept(_Match_mode __match_mode, _StateIdT __i) + { + if (__dfs_mode) + { + __glibcxx_assert(!_M_has_sol); + if (__match_mode == _Match_mode::_Exact) + _M_has_sol = _M_current == _M_end; + else + _M_has_sol = true; + if (_M_current == _M_begin + && (_M_flags & regex_constants::match_not_null)) + _M_has_sol = false; + if (_M_has_sol) { - // Try both and compare the result. - // See "case _S_opcode_accept:" handling above. - _M_dfs(__match_mode, __state._M_alt); - auto __has_sol = _M_has_sol; - _M_has_sol = false; - _M_dfs(__match_mode, __state._M_next); - _M_has_sol |= __has_sol; + if (_M_nfa._M_flags & regex_constants::ECMAScript) + _M_results = _M_cur_results; + else // POSIX + { + __glibcxx_assert(_M_states._M_get_sol_pos()); + // Here's POSIX's logic: match the longest one. However + // we never know which one (lhs or rhs of "|") is longer + // unless we try both of them and compare the results. + // The member variable _M_sol_pos records the end + // position of the last successful match. It's better + // to be larger, because POSIX regex is always greedy. + // TODO: This could be slow. + if (*_M_states._M_get_sol_pos() == _BiIter() + || std::distance(_M_begin, + *_M_states._M_get_sol_pos()) + < std::distance(_M_begin, _M_current)) + { + *_M_states._M_get_sol_pos() = _M_current; + _M_results = _M_cur_results; + } + } } - break; + } + else + { + if (_M_current == _M_begin + && (_M_flags & regex_constants::match_not_null)) + return; + if (__match_mode == _Match_mode::_Prefix || _M_current == _M_end) + if (!_M_has_sol) + { + _M_has_sol = true; + _M_results = _M_cur_results; + } + } + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_handle_alternative(_Match_mode __match_mode, _StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + + if (_M_nfa._M_flags & regex_constants::ECMAScript) + { + // TODO: Fix BFS support. It is wrong. + _M_dfs(__match_mode, __state._M_alt); + // Pick lhs if it matches. Only try rhs if it doesn't. + if (!_M_has_sol) + _M_dfs(__match_mode, __state._M_next); + } + else + { + // Try both and compare the result. + // See "case _S_opcode_accept:" handling above. + _M_dfs(__match_mode, __state._M_alt); + auto __has_sol = _M_has_sol; + _M_has_sol = false; + _M_dfs(__match_mode, __state._M_next); + _M_has_sol |= __has_sol; + } + } + + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_dfs(_Match_mode __match_mode, _StateIdT __i) + { + if (_M_states._M_visited(__i)) + return; + + switch (_M_nfa[__i]._M_opcode()) + { + case _S_opcode_repeat: + _M_handle_repeat(__match_mode, __i); break; + case _S_opcode_subexpr_begin: + _M_handle_subexpr_begin(__match_mode, __i); break; + case _S_opcode_subexpr_end: + _M_handle_subexpr_end(__match_mode, __i); break; + case _S_opcode_line_begin_assertion: + _M_handle_line_begin_assertion(__match_mode, __i); break; + case _S_opcode_line_end_assertion: + _M_handle_line_end_assertion(__match_mode, __i); break; + case _S_opcode_word_boundary: + _M_handle_word_boundary(__match_mode, __i); break; + case _S_opcode_subexpr_lookahead: + _M_handle_subexpr_lookahead(__match_mode, __i); break; + case _S_opcode_match: + _M_handle_match(__match_mode, __i); break; + case _S_opcode_backref: + _M_handle_backref(__match_mode, __i); break; + case _S_opcode_accept: + _M_handle_accept(__match_mode, __i); break; + case _S_opcode_alternative: + _M_handle_alternative(__match_mode, __i); break; default: __glibcxx_assert(false); } @@ -413,6 +495,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: _M_word_boundary() const { + if (_M_current == _M_begin && (_M_flags & regex_constants::match_not_bow)) + return false; + if (_M_current == _M_end && (_M_flags & regex_constants::match_not_eow)) + return false; + bool __left_is_word = false; if (_M_current != _M_begin || (_M_flags & regex_constants::match_prev_avail)) @@ -424,13 +511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool __right_is_word = _M_current != _M_end && _M_is_word(*_M_current); - if (__left_is_word == __right_is_word) - return false; - if (__left_is_word && !(_M_flags & regex_constants::match_not_eow)) - return true; - if (__right_is_word && !(_M_flags & regex_constants::match_not_bow)) - return true; - return false; + return __left_is_word != __right_is_word; } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/regex_scanner.h b/libstdc++-v3/include/bits/regex_scanner.h index 37dea840d5..37ad862a66 100644 --- a/libstdc++-v3/include/bits/regex_scanner.h +++ b/libstdc++-v3/include/bits/regex_scanner.h @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -43,7 +43,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { public: /// Token types returned from the scanner. - enum _TokenT + enum _TokenT : unsigned { _S_token_anychar, _S_token_ord_char, @@ -73,7 +73,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_token_comma, _S_token_dup_count, _S_token_eof, - _S_token_unknown + _S_token_bracket_dash, + _S_token_unknown = -1u }; protected: diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc index fedba09a71..ad0b0477f3 100644 --- a/libstdc++-v3/include/bits/regex_scanner.tcc +++ b/libstdc++-v3/include/bits/regex_scanner.tcc @@ -1,6 +1,6 @@ // class template regex -*- C++ -*- -// Copyright (C) 2013-2016 Free Software Foundation, Inc. +// Copyright (C) 2013-2017 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 @@ -210,7 +210,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __c = *_M_current++; - if (__c == '[') + if (__c == '-') + _M_token = _S_token_bracket_dash; + else if (__c == '[') { if (_M_current == _M_end) __throw_regex_error(regex_constants::error_brack, diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index b22477e96b..fe933ff2af 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -1,6 +1,6 @@ // shared_ptr and weak_ptr implementation -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -92,17 +92,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> class shared_ptr : public __shared_ptr<_Tp> { - template<typename _Ptr> - using _Convertible - = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; + template<typename... _Args> + using _Constructible = typename enable_if< + is_constructible<__shared_ptr<_Tp>, _Args...>::value + >::type; + + template<typename _Arg> + using _Assignable = typename enable_if< + is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr& + >::type; public: + + using element_type = typename __shared_ptr<_Tp>::element_type; + +#if __cplusplus > 201402L +# define __cpp_lib_shared_ptr_weak_type 201606 + using weak_type = weak_ptr<_Tp>; +#endif /** * @brief Construct an empty %shared_ptr. * @post use_count()==0 && get()==0 */ - constexpr shared_ptr() noexcept - : __shared_ptr<_Tp>() { } + constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { } shared_ptr(const shared_ptr&) noexcept = default; @@ -112,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @post use_count() == 1 && get() == __p * @throw std::bad_alloc, in which case @c delete @a __p is called. */ - template<typename _Tp1> - explicit shared_ptr(_Tp1* __p) - : __shared_ptr<_Tp>(__p) { } + template<typename _Yp, typename = _Constructible<_Yp*>> + explicit + shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { } /** * @brief Construct a %shared_ptr that owns the pointer @a __p @@ -129,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * __shared_ptr will release __p by calling __d(__p) */ - template<typename _Tp1, typename _Deleter> - shared_ptr(_Tp1* __p, _Deleter __d) + template<typename _Yp, typename _Deleter, + typename = _Constructible<_Yp*, _Deleter>> + shared_ptr(_Yp* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) { } /** @@ -165,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * __shared_ptr will release __p by calling __d(__p) */ - template<typename _Tp1, typename _Deleter, typename _Alloc> - shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) + template<typename _Yp, typename _Deleter, typename _Alloc, + typename = _Constructible<_Yp*, _Deleter, _Alloc>> + shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) : __shared_ptr<_Tp>(__p, __d, std::move(__a)) { } /** @@ -206,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * assert(pii.use_count() == 2); * @endcode */ - template<typename _Tp1> - shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept + template<typename _Yp> + shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept : __shared_ptr<_Tp>(__r, __p) { } /** @@ -217,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __r A %shared_ptr. * @post get() == __r.get() && use_count() == __r.use_count() */ - template<typename _Tp1, typename = _Convertible<_Tp1*>> - shared_ptr(const shared_ptr<_Tp1>& __r) noexcept + template<typename _Yp, + typename = _Constructible<const shared_ptr<_Yp>&>> + shared_ptr(const shared_ptr<_Yp>& __r) noexcept : __shared_ptr<_Tp>(__r) { } /** @@ -234,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __r A %shared_ptr rvalue. * @post *this contains the old value of @a __r, @a __r is empty. */ - template<typename _Tp1, typename = _Convertible<_Tp1*>> - shared_ptr(shared_ptr<_Tp1>&& __r) noexcept + template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>> + shared_ptr(shared_ptr<_Yp>&& __r) noexcept : __shared_ptr<_Tp>(std::move(__r)) { } /** @@ -246,22 +261,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @throw bad_weak_ptr when __r.expired(), * in which case the constructor has no effect. */ - template<typename _Tp1> - explicit shared_ptr(const weak_ptr<_Tp1>& __r) + template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>> + explicit shared_ptr(const weak_ptr<_Yp>& __r) : __shared_ptr<_Tp>(__r) { } #if _GLIBCXX_USE_DEPRECATED - template<typename _Tp1> - shared_ptr(std::auto_ptr<_Tp1>&& __r); + template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>> + shared_ptr(auto_ptr<_Yp>&& __r); #endif // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2399. shared_ptr's constructor from unique_ptr should be constrained - template<typename _Tp1, typename _Del, typename - = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>> - shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + template<typename _Yp, typename _Del, + typename = _Constructible<unique_ptr<_Yp, _Del>>> + shared_ptr(unique_ptr<_Yp, _Del>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } +#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED + // This non-standard constructor exists to support conversions that + // were possible in C++11 and C++14 but are ill-formed in C++17. + // If an exception is thrown this constructor has no effect. + template<typename _Yp, typename _Del, + _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0> + shared_ptr(unique_ptr<_Yp, _Del>&& __r) + : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { } +#endif + /** * @brief Construct an empty %shared_ptr. * @post use_count() == 0 && get() == nullptr @@ -270,18 +295,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_ptr& operator=(const shared_ptr&) noexcept = default; - template<typename _Tp1> - shared_ptr& - operator=(const shared_ptr<_Tp1>& __r) noexcept + template<typename _Yp> + _Assignable<const shared_ptr<_Yp>&> + operator=(const shared_ptr<_Yp>& __r) noexcept { this->__shared_ptr<_Tp>::operator=(__r); return *this; } #if _GLIBCXX_USE_DEPRECATED - template<typename _Tp1> - shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) + template<typename _Yp> + _Assignable<auto_ptr<_Yp>> + operator=(auto_ptr<_Yp>&& __r) { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; @@ -295,17 +320,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template<class _Tp1> - shared_ptr& - operator=(shared_ptr<_Tp1>&& __r) noexcept + template<class _Yp> + _Assignable<shared_ptr<_Yp>> + operator=(shared_ptr<_Yp>&& __r) noexcept { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; } - template<typename _Tp1, typename _Del> - shared_ptr& - operator=(std::unique_ptr<_Tp1, _Del>&& __r) + template<typename _Yp, typename _Del> + _Assignable<unique_ptr<_Yp, _Del>> + operator=(unique_ptr<_Yp, _Del>&& __r) { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; @@ -319,8 +344,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) { } - template<typename _Tp1, typename _Alloc, typename... _Args> - friend shared_ptr<_Tp1> + template<typename _Yp, typename _Alloc, typename... _Args> + friend shared_ptr<_Yp> allocate_shared(const _Alloc& __a, _Args&&... __args); // This constructor is non-standard, it is used by weak_ptr::lock(). @@ -330,11 +355,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend class weak_ptr<_Tp>; }; +#if __cpp_deduction_guides >= 201606 + template<typename _Tp> + shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; + template<typename _Tp, typename _Del> + shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>; +#endif + // 20.7.2.2.7 shared_ptr comparisons - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator==(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return __a.get() == __b.get(); } template<typename _Tp> @@ -347,10 +378,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return !__a; } - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator!=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return __a.get() != __b.get(); } template<typename _Tp> @@ -363,29 +393,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return (bool)__a; } - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator<(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { - typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; - return std::less<_CT>()(__a.get(), __b.get()); + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + using _Up_elt = typename shared_ptr<_Up>::element_type; + using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; + return less<_Vp>()(__a.get(), __b.get()); } template<typename _Tp> inline bool operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + return less<_Tp_elt*>()(__a.get(), nullptr); + } template<typename _Tp> inline bool operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { + using _Tp_elt = typename shared_ptr<_Tp>::element_type; + return less<_Tp_elt*>()(nullptr, __a.get()); + } - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator<=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return !(__b < __a); } template<typename _Tp> @@ -398,26 +434,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept { return !(__a < nullptr); } - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator>(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return (__b < __a); } template<typename _Tp> inline bool operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { return nullptr < __a; } template<typename _Tp> inline bool operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { return __a < nullptr; } - template<typename _Tp1, typename _Tp2> + template<typename _Tp, typename _Up> inline bool - operator>=(const shared_ptr<_Tp1>& __a, - const shared_ptr<_Tp2>& __b) noexcept + operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept { return !(__a < __b); } template<typename _Tp> @@ -441,25 +475,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __a.swap(__b); } // 20.7.2.2.9 shared_ptr casts. - template<typename _Tp, typename _Tp1> + template<typename _Tp, typename _Up> inline shared_ptr<_Tp> - static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept - { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); } + static_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get())); + } - template<typename _Tp, typename _Tp1> + template<typename _Tp, typename _Up> inline shared_ptr<_Tp> - const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept - { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); } + const_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get())); + } - template<typename _Tp, typename _Tp1> + template<typename _Tp, typename _Up> inline shared_ptr<_Tp> - dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept + dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept { - if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return shared_ptr<_Tp>(__r, __p); - return shared_ptr<_Tp>(); + using _Sp = shared_ptr<_Tp>; + if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get())) + return _Sp(__r, __p); + return _Sp(); } +#if __cplusplus > 201402L + template<typename _Tp, typename _Up> + inline shared_ptr<_Tp> + reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept + { + using _Sp = shared_ptr<_Tp>; + return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get())); + } +#endif /** * @brief A smart pointer with weak semantics. @@ -469,43 +519,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> class weak_ptr : public __weak_ptr<_Tp> { - template<typename _Ptr> - using _Convertible - = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; + template<typename _Arg> + using _Constructible = typename enable_if< + is_constructible<__weak_ptr<_Tp>, _Arg>::value + >::type; + + template<typename _Arg> + using _Assignable = typename enable_if< + is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr& + >::type; public: constexpr weak_ptr() noexcept = default; - template<typename _Tp1, typename = _Convertible<_Tp1*>> - weak_ptr(const shared_ptr<_Tp1>& __r) noexcept + template<typename _Yp, + typename = _Constructible<const shared_ptr<_Yp>&>> + weak_ptr(const shared_ptr<_Yp>& __r) noexcept : __weak_ptr<_Tp>(__r) { } weak_ptr(const weak_ptr&) noexcept = default; - template<typename _Tp1, typename = _Convertible<_Tp1*>> - weak_ptr(const weak_ptr<_Tp1>& __r) noexcept + template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>> + weak_ptr(const weak_ptr<_Yp>& __r) noexcept : __weak_ptr<_Tp>(__r) { } weak_ptr(weak_ptr&&) noexcept = default; - template<typename _Tp1, typename = _Convertible<_Tp1*>> - weak_ptr(weak_ptr<_Tp1>&& __r) noexcept + template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>> + weak_ptr(weak_ptr<_Yp>&& __r) noexcept : __weak_ptr<_Tp>(std::move(__r)) { } weak_ptr& operator=(const weak_ptr& __r) noexcept = default; - template<typename _Tp1> - weak_ptr& - operator=(const weak_ptr<_Tp1>& __r) noexcept + template<typename _Yp> + _Assignable<const weak_ptr<_Yp>&> + operator=(const weak_ptr<_Yp>& __r) noexcept { this->__weak_ptr<_Tp>::operator=(__r); return *this; } - template<typename _Tp1> - weak_ptr& - operator=(const shared_ptr<_Tp1>& __r) noexcept + template<typename _Yp> + _Assignable<const shared_ptr<_Yp>&> + operator=(const shared_ptr<_Yp>& __r) noexcept { this->__weak_ptr<_Tp>::operator=(__r); return *this; @@ -514,9 +571,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION weak_ptr& operator=(weak_ptr&& __r) noexcept = default; - template<typename _Tp1> - weak_ptr& - operator=(weak_ptr<_Tp1>&& __r) noexcept + template<typename _Yp> + _Assignable<weak_ptr<_Yp>> + operator=(weak_ptr<_Yp>&& __r) noexcept { this->__weak_ptr<_Tp>::operator=(std::move(__r)); return *this; @@ -527,6 +584,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return shared_ptr<_Tp>(*this, std::nothrow); } }; +#if __cpp_deduction_guides >= 201606 + template<typename _Tp> + weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; +#endif + // 20.7.2.3.6 weak_ptr specialized algorithms. template<typename _Tp> inline void @@ -535,9 +597,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Primary template owner_less - template<typename _Tp> + template<typename _Tp = void> struct owner_less; + /// Void specialization of owner_less + template<> + struct owner_less<void> : _Sp_owner_less<void, void> + { }; + /// Partial specialization of owner_less for shared_ptr. template<typename _Tp> struct owner_less<shared_ptr<_Tp>> @@ -576,31 +643,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_from_this() const { return shared_ptr<const _Tp>(this->_M_weak_this); } +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 +#define __cpp_lib_enable_shared_from_this 201603 + weak_ptr<_Tp> + weak_from_this() noexcept + { return this->_M_weak_this; } + + weak_ptr<const _Tp> + weak_from_this() const noexcept + { return this->_M_weak_this; } +#endif + private: template<typename _Tp1> void _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept { _M_weak_this._M_assign(__p, __n); } - template<typename _Tp1, typename _Tp2> - friend void - __enable_shared_from_this_helper(const __shared_count<>&, - const enable_shared_from_this<_Tp1>*, - const _Tp2*) noexcept; + // Found by ADL when this is an associated class. + friend const enable_shared_from_this* + __enable_shared_from_this_base(const __shared_count<>&, + const enable_shared_from_this* __p) + { return __p; } + + template<typename, _Lock_policy> + friend class __shared_ptr; mutable weak_ptr<_Tp> _M_weak_this; }; - template<typename _Tp1, typename _Tp2> - inline void - __enable_shared_from_this_helper(const __shared_count<>& __pn, - const enable_shared_from_this<_Tp1>* - __pe, const _Tp2* __px) noexcept - { - if (__pe != nullptr) - __pe->_M_weak_assign(const_cast<_Tp2*>(__px), __pn); - } - /** * @brief Create an object that is owned by a shared_ptr. * @param __a An allocator. @@ -643,7 +714,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { size_t operator()(const shared_ptr<_Tp>& __s) const noexcept - { return std::hash<_Tp*>()(__s.get()); } + { + return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get()); + } }; // @} group pointer_abstractions diff --git a/libstdc++-v3/include/bits/shared_ptr_atomic.h b/libstdc++-v3/include/bits/shared_ptr_atomic.h index ad58ebb4fd..d05d686557 100644 --- a/libstdc++-v3/include/bits/shared_ptr_atomic.h +++ b/libstdc++-v3/include/bits/shared_ptr_atomic.h @@ -1,6 +1,6 @@ // shared_ptr atomic access -*- C++ -*- -// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// Copyright (C) 2014-2017 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 diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index e844c9c91f..c8d7f20d5d 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1,6 +1,6 @@ // shared_ptr and weak_ptr implementation details -*- C++ -*- -// Copyright (C) 2007-2016 Free Software Foundation, Inc. +// Copyright (C) 2007-2017 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 @@ -49,8 +49,12 @@ #ifndef _SHARED_PTR_BASE_H #define _SHARED_PTR_BASE_H 1 -#include <typeinfo> +#if __cpp_rtti +# include <typeinfo> +#endif #include <bits/allocated_ptr.h> +#include <bits/refwrap.h> +#include <bits/stl_function.h> #include <ext/aligned_buffer.h> namespace std _GLIBCXX_VISIBILITY(default) @@ -70,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: virtual char const* what() const noexcept; - virtual ~bad_weak_ptr() noexcept; + virtual ~bad_weak_ptr() noexcept; }; // Substitute for bad_weak_ptr object in the case of -fno-exceptions. @@ -108,31 +112,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class _Sp_counted_base : public _Mutex_base<_Lp> { - public: + public: _Sp_counted_base() noexcept : _M_use_count(1), _M_weak_count(1) { } - + virtual ~_Sp_counted_base() noexcept { } - + // Called when _M_use_count drops to zero, to release the resources // managed by *this. virtual void _M_dispose() noexcept = 0; - + // Called when _M_weak_count drops to zero. virtual void _M_destroy() noexcept { delete this; } - + virtual void* _M_get_deleter(const std::type_info&) noexcept = 0; void _M_add_ref_copy() { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); } - + void _M_add_ref_lock(); @@ -167,7 +171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } } - + void _M_weak_add_ref() noexcept { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); } @@ -189,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_destroy(); } } - + long _M_get_use_count() const noexcept { @@ -198,7 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); } - private: + private: _Sp_counted_base(_Sp_counted_base const&) = delete; _Sp_counted_base& operator=(_Sp_counted_base const&) = delete; @@ -229,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - template<> + template<> inline void _Sp_counted_base<_S_atomic>:: _M_add_ref_lock() @@ -241,10 +245,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__count == 0) __throw_bad_weak_ptr(); // Replace the current counter value with the old value + 1, as - // long as it's not changed meanwhile. + // long as it's not changed meanwhile. } while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, - true, __ATOMIC_ACQ_REL, + true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)); } @@ -555,6 +559,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Impl _M_impl; }; + // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>. + struct __sp_array_delete + { + template<typename _Yp> + void operator()(_Yp* __p) const { delete[] __p; } + }; template<_Lock_policy _Lp> class __shared_count @@ -578,6 +588,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template<typename _Ptr> + __shared_count(_Ptr __p, /* is_array = */ false_type) + : __shared_count(__p) + { } + + template<typename _Ptr> + __shared_count(_Ptr __p, /* is_array = */ true_type) + : __shared_count(__p, __sp_array_delete{}, allocator<void>()) + { } + template<typename _Ptr, typename _Deleter> __shared_count(_Ptr __p, _Deleter __d) : __shared_count(__p, std::move(__d), allocator<void>()) @@ -844,68 +864,240 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_pi = nullptr; } - // Support for enable_shared_from_this. +#define __cpp_lib_shared_ptr_arrays 201603 - // Friend of __enable_shared_from_this. - template<_Lock_policy _Lp, typename _Tp1, typename _Tp2> - void - __enable_shared_from_this_helper(const __shared_count<_Lp>&, - const __enable_shared_from_this<_Tp1, - _Lp>*, const _Tp2*) noexcept; + // Helper traits for shared_ptr of array: - // Friend of enable_shared_from_this. - template<typename _Tp1, typename _Tp2> - void - __enable_shared_from_this_helper(const __shared_count<>&, - const enable_shared_from_this<_Tp1>*, - const _Tp2*) noexcept; + // A pointer type Y* is said to be compatible with a pointer type T* when + // either Y* is convertible to T* or Y is U[N] and T is U cv []. + template<typename _Yp_ptr, typename _Tp_ptr> + struct __sp_compatible_with + : false_type + { }; - template<_Lock_policy _Lp> - inline void - __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) noexcept - { } + template<typename _Yp, typename _Tp> + struct __sp_compatible_with<_Yp*, _Tp*> + : is_convertible<_Yp*, _Tp*>::type + { }; + + template<typename _Up, size_t _Nm> + struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]> + : true_type + { }; + + template<typename _Up, size_t _Nm> + struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]> + : true_type + { }; + + template<typename _Up, size_t _Nm> + struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]> + : true_type + { }; + + template<typename _Up, size_t _Nm> + struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]> + : true_type + { }; + + // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N]. + template<typename _Up, size_t _Nm, typename _Yp, typename = void> + struct __sp_is_constructible_arrN + : false_type + { }; + + template<typename _Up, size_t _Nm, typename _Yp> + struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>> + : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type + { }; + + // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[]. + template<typename _Up, typename _Yp, typename = void> + struct __sp_is_constructible_arr + : false_type + { }; + + template<typename _Up, typename _Yp> + struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>> + : is_convertible<_Yp(*)[], _Up(*)[]>::type + { }; + + // Trait to check if shared_ptr<T> can be constructed from Y*. + template<typename _Tp, typename _Yp> + struct __sp_is_constructible; + + // When T is U[N], Y(*)[N] shall be convertible to T*; + template<typename _Up, size_t _Nm, typename _Yp> + struct __sp_is_constructible<_Up[_Nm], _Yp> + : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type + { }; + + // when T is U[], Y(*)[] shall be convertible to T*; + template<typename _Up, typename _Yp> + struct __sp_is_constructible<_Up[], _Yp> + : __sp_is_constructible_arr<_Up, _Yp>::type + { }; + + // otherwise, Y* shall be convertible to T*. + template<typename _Tp, typename _Yp> + struct __sp_is_constructible + : is_convertible<_Yp*, _Tp*>::type + { }; + + + // Define operator* and operator-> for shared_ptr<T>. + template<typename _Tp, _Lock_policy _Lp, + bool = is_array<_Tp>::value, bool = is_void<_Tp>::value> + class __shared_ptr_access + { + public: + using element_type = _Tp; + + element_type& + operator*() const noexcept + { + __glibcxx_assert(_M_get() != nullptr); + return *_M_get(); + } + + element_type* + operator->() const noexcept + { + _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); + return _M_get(); + } + + private: + element_type* + _M_get() const noexcept + { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } + }; + + // Define operator-> for shared_ptr<cv void>. + template<typename _Tp, _Lock_policy _Lp> + class __shared_ptr_access<_Tp, _Lp, false, true> + { + public: + using element_type = _Tp; + + element_type* + operator->() const noexcept + { + auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); + _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr); + return __ptr; + } + }; + + // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>. + template<typename _Tp, _Lock_policy _Lp> + class __shared_ptr_access<_Tp, _Lp, true, false> + { + public: + using element_type = typename remove_extent<_Tp>::type; + +#if __cplusplus <= 201402L + [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]] + element_type& + operator*() const noexcept + { + __glibcxx_assert(_M_get() != nullptr); + return *_M_get(); + } + + [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]] + element_type* + operator->() const noexcept + { + _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); + return _M_get(); + } +#endif + + element_type& + operator[](ptrdiff_t __i) const + { + __glibcxx_assert(_M_get() != nullptr); + __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value); + return _M_get()[__i]; + } + private: + element_type* + _M_get() const noexcept + { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } + }; template<typename _Tp, _Lock_policy _Lp> class __shared_ptr + : public __shared_ptr_access<_Tp, _Lp> { - template<typename _Ptr> - using _Convertible - = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; + public: + using element_type = typename remove_extent<_Tp>::type; + + private: + // Constraint for taking ownership of a pointer of type _Yp*: + template<typename _Yp> + using _SafeConv + = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type; + + // Constraint for construction from shared_ptr and weak_ptr: + template<typename _Yp, typename _Res = void> + using _Compatible = typename + enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; + + // Constraint for assignment from shared_ptr and weak_ptr: + template<typename _Yp> + using _Assignable = _Compatible<_Yp, __shared_ptr&>; + + // Constraint for construction from unique_ptr: + template<typename _Yp, typename _Del, typename _Res = void, + typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer> + using _UniqCompatible = typename enable_if<__and_< + __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*> + >::value, _Res>::type; + + // Constraint for assignment from unique_ptr: + template<typename _Yp, typename _Del> + using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>; public: - typedef _Tp element_type; + +#if __cplusplus > 201402L + using weak_type = __weak_ptr<_Tp, _Lp>; +#endif constexpr __shared_ptr() noexcept : _M_ptr(0), _M_refcount() { } - template<typename _Tp1> - explicit __shared_ptr(_Tp1* __p) - : _M_ptr(__p), _M_refcount(__p) + template<typename _Yp, typename = _SafeConv<_Yp>> + explicit + __shared_ptr(_Yp* __p) + : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - static_assert( !is_void<_Tp1>::value, "incomplete type" ); - static_assert( sizeof(_Tp1) > 0, "incomplete type" ); - __enable_shared_from_this_helper(_M_refcount, __p, __p); + static_assert( !is_void<_Yp>::value, "incomplete type" ); + static_assert( sizeof(_Yp) > 0, "incomplete type" ); + _M_enable_shared_from_this_with(__p); } - template<typename _Tp1, typename _Deleter> - __shared_ptr(_Tp1* __p, _Deleter __d) + template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>> + __shared_ptr(_Yp* __p, _Deleter __d) : _M_ptr(__p), _M_refcount(__p, __d) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed - __enable_shared_from_this_helper(_M_refcount, __p, __p); + static_assert(__is_invocable<_Deleter&, _Yp*&>::value, + "deleter expression d(p) is well-formed"); + _M_enable_shared_from_this_with(__p); } - template<typename _Tp1, typename _Deleter, typename _Alloc> - __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) + template<typename _Yp, typename _Deleter, typename _Alloc, + typename = _SafeConv<_Yp>> + __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) : _M_ptr(__p), _M_refcount(__p, __d, std::move(__a)) { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed - __enable_shared_from_this_helper(_M_refcount, __p, __p); + static_assert(__is_invocable<_Deleter&, _Yp*&>::value, + "deleter expression d(p) is well-formed"); + _M_enable_shared_from_this_with(__p); } template<typename _Deleter> @@ -918,8 +1110,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(0), _M_refcount(__p, __d, std::move(__a)) { } - template<typename _Tp1> - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept + template<typename _Yp> + __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r, + element_type* __p) noexcept : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws { } @@ -927,8 +1120,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_ptr& operator=(const __shared_ptr&) noexcept = default; ~__shared_ptr() = default; - template<typename _Tp1, typename = _Convertible<_Tp1*>> - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp, typename = _Compatible<_Yp>> + __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) { } @@ -939,48 +1132,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __r._M_ptr = 0; } - template<typename _Tp1, typename = _Convertible<_Tp1*>> - __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept + template<typename _Yp, typename = _Compatible<_Yp>> + __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount() { _M_refcount._M_swap(__r._M_refcount); __r._M_ptr = 0; } - template<typename _Tp1> - explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) + template<typename _Yp, typename = _Compatible<_Yp>> + explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r) : _M_refcount(__r._M_refcount) // may throw { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // It is now safe to copy __r._M_ptr, as // _M_refcount(__r._M_refcount) did not throw. _M_ptr = __r._M_ptr; } // If an exception is thrown this constructor has no effect. - template<typename _Tp1, typename _Del, typename - = _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>> - __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + template<typename _Yp, typename _Del, + typename = _UniqCompatible<_Yp, _Del>> + __shared_ptr(unique_ptr<_Yp, _Del>&& __r) : _M_ptr(__r.get()), _M_refcount() { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) auto __raw = _S_raw_ptr(__r.get()); _M_refcount = __shared_count<_Lp>(std::move(__r)); - __enable_shared_from_this_helper(_M_refcount, __raw, __raw); + _M_enable_shared_from_this_with(__raw); } +#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED + protected: + // If an exception is thrown this constructor has no effect. + template<typename _Tp1, typename _Del, + typename enable_if<__and_< + __not_<is_array<_Tp>>, is_array<_Tp1>, + is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*> + >::value, bool>::type = true> + __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete) + : _M_ptr(__r.get()), _M_refcount() + { + auto __raw = _S_raw_ptr(__r.get()); + _M_refcount = __shared_count<_Lp>(std::move(__r)); + _M_enable_shared_from_this_with(__raw); + } + public: +#endif + #if _GLIBCXX_USE_DEPRECATED // Postcondition: use_count() == 1 and __r.get() == 0 - template<typename _Tp1> - __shared_ptr(std::auto_ptr<_Tp1>&& __r); + template<typename _Yp, typename = _Compatible<_Yp>> + __shared_ptr(auto_ptr<_Yp>&& __r); #endif constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { } - template<typename _Tp1> - __shared_ptr& - operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp> + _Assignable<_Yp> + operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r._M_ptr; _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw @@ -988,9 +1196,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if _GLIBCXX_USE_DEPRECATED - template<typename _Tp1> - __shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) + template<typename _Yp> + _Assignable<_Yp> + operator=(auto_ptr<_Yp>&& __r) { __shared_ptr(std::move(__r)).swap(*this); return *this; @@ -1004,17 +1212,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template<class _Tp1> - __shared_ptr& - operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept + template<class _Yp> + _Assignable<_Yp> + operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept { __shared_ptr(std::move(__r)).swap(*this); return *this; } - template<typename _Tp1, typename _Del> - __shared_ptr& - operator=(std::unique_ptr<_Tp1, _Del>&& __r) + template<typename _Yp, typename _Del> + _UniqAssignable<_Yp, _Del> + operator=(unique_ptr<_Yp, _Del>&& __r) { __shared_ptr(std::move(__r)).swap(*this); return *this; @@ -1024,41 +1232,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reset() noexcept { __shared_ptr().swap(*this); } - template<typename _Tp1> - void - reset(_Tp1* __p) // _Tp1 must be complete. + template<typename _Yp> + _SafeConv<_Yp> + reset(_Yp* __p) // _Yp must be complete. { // Catch self-reset errors. __glibcxx_assert(__p == 0 || __p != _M_ptr); __shared_ptr(__p).swap(*this); } - template<typename _Tp1, typename _Deleter> - void - reset(_Tp1* __p, _Deleter __d) + template<typename _Yp, typename _Deleter> + _SafeConv<_Yp> + reset(_Yp* __p, _Deleter __d) { __shared_ptr(__p, __d).swap(*this); } - template<typename _Tp1, typename _Deleter, typename _Alloc> - void - reset(_Tp1* __p, _Deleter __d, _Alloc __a) + template<typename _Yp, typename _Deleter, typename _Alloc> + _SafeConv<_Yp> + reset(_Yp* __p, _Deleter __d, _Alloc __a) { __shared_ptr(__p, __d, std::move(__a)).swap(*this); } - // Allow class instantiation when _Tp is [cv-qual] void. - typename std::add_lvalue_reference<_Tp>::type - operator*() const noexcept - { - __glibcxx_assert(_M_ptr != 0); - return *_M_ptr; - } - - _Tp* - operator->() const noexcept - { - _GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0); - return _M_ptr; - } - - _Tp* + element_type* get() const noexcept { return _M_ptr; } @@ -1103,7 +1296,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // This relies on _Sp_counted_ptr_inplace::_M_get_deleter. void* __p = _M_refcount._M_get_deleter(typeid(__tag)); _M_ptr = static_cast<_Tp*>(__p); - __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); + _M_enable_shared_from_this_with(_M_ptr); } #else template<typename _Alloc> @@ -1135,7 +1328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_count<_Lp> __count(__ptr, __del, __del._M_alloc); _M_refcount._M_swap(__count); _M_ptr = __ptr; - __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); + _M_enable_shared_from_this_with(_M_ptr); } #endif @@ -1155,6 +1348,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend class __weak_ptr<_Tp, _Lp>; private: + + template<typename _Yp> + using __esft_base_t = decltype(__enable_shared_from_this_base( + std::declval<const __shared_count<_Lp>&>(), + std::declval<_Yp*>())); + + // Detect an accessible and unambiguous enable_shared_from_this base. + template<typename _Yp, typename = void> + struct __has_esft_base + : false_type { }; + + template<typename _Yp> + struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>> + : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays + + template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> + typename enable_if<__has_esft_base<_Yp2>::value>::type + _M_enable_shared_from_this_with(_Yp* __p) noexcept + { + if (auto __base = __enable_shared_from_this_base(_M_refcount, __p)) + __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount); + } + + template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> + typename enable_if<!__has_esft_base<_Yp2>::value>::type + _M_enable_shared_from_this_with(_Yp*) noexcept + { } + void* _M_get_deleter(const std::type_info& __ti) const noexcept { return _M_refcount._M_get_deleter(__ti); } @@ -1175,7 +1396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Del, typename _Tp1, _Lock_policy _Lp1> friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; - _Tp* _M_ptr; // Contained pointer. + element_type* _M_ptr; // Contained pointer. __shared_count<_Lp> _M_refcount; // Reference counter. }; @@ -1213,24 +1434,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept { return (bool)__a; } - template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> + template<typename _Tp, typename _Up, _Lock_policy _Lp> inline bool - operator<(const __shared_ptr<_Tp1, _Lp>& __a, - const __shared_ptr<_Tp2, _Lp>& __b) noexcept + operator<(const __shared_ptr<_Tp, _Lp>& __a, + const __shared_ptr<_Up, _Lp>& __b) noexcept { - typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; - return std::less<_CT>()(__a.get(), __b.get()); + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type; + using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; + return less<_Vp>()(__a.get(), __b.get()); } template<typename _Tp, _Lock_policy _Lp> inline bool operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + return less<_Tp_elt*>()(__a.get(), nullptr); + } template<typename _Tp, _Lock_policy _Lp> inline bool operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { + using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; + return less<_Tp_elt*>()(nullptr, __a.get()); + } template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> inline bool @@ -1257,12 +1486,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, _Lock_policy _Lp> inline bool operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept - { return std::less<_Tp*>()(nullptr, __a.get()); } + { return nullptr < __a; } template<typename _Tp, _Lock_policy _Lp> inline bool operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept - { return std::less<_Tp*>()(__a.get(), nullptr); } + { return __a < nullptr; } template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> inline bool @@ -1312,7 +1541,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Tp1, _Lock_policy _Lp> inline __shared_ptr<_Tp, _Lp> static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept - { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); } + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get())); + } // The seemingly equivalent code: // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) @@ -1322,7 +1554,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Tp1, _Lock_policy _Lp> inline __shared_ptr<_Tp, _Lp> const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept - { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); } + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get())); + } // The seemingly equivalent code: // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) @@ -1333,21 +1568,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline __shared_ptr<_Tp, _Lp> dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept { - if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return __shared_ptr<_Tp, _Lp>(__r, __p); - return __shared_ptr<_Tp, _Lp>(); + using _Sp = __shared_ptr<_Tp, _Lp>; + if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get())) + return _Sp(__r, __p); + return _Sp(); } +#if __cplusplus > 201402L + template<typename _Tp, typename _Tp1, _Lock_policy _Lp> + inline __shared_ptr<_Tp, _Lp> + reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + { + using _Sp = __shared_ptr<_Tp, _Lp>; + return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get())); + } +#endif template<typename _Tp, _Lock_policy _Lp> class __weak_ptr { - template<typename _Ptr> - using _Convertible - = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; + template<typename _Yp, typename _Res = void> + using _Compatible = typename + enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; + + // Constraint for assignment from shared_ptr and weak_ptr: + template<typename _Yp> + using _Assignable = _Compatible<_Yp, __weak_ptr&>; public: - typedef _Tp element_type; + using element_type = typename remove_extent<_Tp>::type; constexpr __weak_ptr() noexcept : _M_ptr(nullptr), _M_refcount() @@ -1371,13 +1620,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // // It is not possible to avoid spurious access violations since // in multithreaded programs __r._M_ptr may be invalidated at any point. - template<typename _Tp1, typename = _Convertible<_Tp1*>> - __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp, typename = _Compatible<_Yp>> + __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept : _M_refcount(__r._M_refcount) { _M_ptr = __r.lock().get(); } - template<typename _Tp1, typename = _Convertible<_Tp1*>> - __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp, typename = _Compatible<_Yp>> + __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) { } @@ -1385,26 +1634,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) { __r._M_ptr = nullptr; } - template<typename _Tp1, typename = _Convertible<_Tp1*>> - __weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept + template<typename _Yp, typename = _Compatible<_Yp>> + __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) { __r._M_ptr = nullptr; } __weak_ptr& operator=(const __weak_ptr& __r) noexcept = default; - template<typename _Tp1> - __weak_ptr& - operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp> + _Assignable<_Yp> + operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r.lock().get(); _M_refcount = __r._M_refcount; return *this; } - template<typename _Tp1> - __weak_ptr& - operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept + template<typename _Yp> + _Assignable<_Yp> + operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept { _M_ptr = __r._M_ptr; _M_refcount = __r._M_refcount; @@ -1420,9 +1669,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template<typename _Tp1> - __weak_ptr& - operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept + template<typename _Yp> + _Assignable<_Yp> + operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept { _M_ptr = __r.lock().get(); _M_refcount = std::move(__r._M_refcount); @@ -1480,7 +1729,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend class __enable_shared_from_this<_Tp, _Lp>; friend class enable_shared_from_this<_Tp>; - _Tp* _M_ptr; // Contained pointer. + element_type* _M_ptr; // Contained pointer. __weak_count<_Lp> _M_refcount; // Reference counter. }; @@ -1506,6 +1755,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.owner_before(__rhs); } }; + template<> + struct _Sp_owner_less<void, void> + { + template<typename _Tp, typename _Up> + auto + operator()(const _Tp& __lhs, const _Up& __rhs) const + -> decltype(__lhs.owner_before(__rhs)) + { return __lhs.owner_before(__rhs); } + + using is_transparent = void; + }; + template<typename _Tp, _Lock_policy _Lp> struct owner_less<__shared_ptr<_Tp, _Lp>> : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> @@ -1540,32 +1801,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_from_this() const { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + __weak_ptr<_Tp, _Lp> + weak_from_this() noexcept + { return this->_M_weak_this; } + + __weak_ptr<const _Tp, _Lp> + weak_from_this() const noexcept + { return this->_M_weak_this; } +#endif + private: template<typename _Tp1> void _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept { _M_weak_this._M_assign(__p, __n); } - template<_Lock_policy _Lp1, typename _Tp1, typename _Tp2> - friend void - __enable_shared_from_this_helper(const __shared_count<_Lp1>&, - const __enable_shared_from_this<_Tp1, - _Lp1>*, const _Tp2*) noexcept; + friend const __enable_shared_from_this* + __enable_shared_from_this_base(const __shared_count<_Lp>&, + const __enable_shared_from_this* __p) + { return __p; } + + template<typename, _Lock_policy> + friend class __shared_ptr; mutable __weak_ptr<_Tp, _Lp> _M_weak_this; }; - template<_Lock_policy _Lp1, typename _Tp1, typename _Tp2> - inline void - __enable_shared_from_this_helper(const __shared_count<_Lp1>& __pn, - const __enable_shared_from_this<_Tp1, - _Lp1>* __pe, - const _Tp2* __px) noexcept - { - if (__pe != nullptr) - __pe->_M_weak_assign(const_cast<_Tp2*>(__px), __pn); - } - template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args> inline __shared_ptr<_Tp, _Lp> __allocate_shared(const _Alloc& __a, _Args&&... __args) @@ -1590,7 +1852,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { size_t operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept - { return std::hash<_Tp*>()(__s.get()); } + { + return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()( + __s.get()); + } }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/slice_array.h b/libstdc++-v3/include/bits/slice_array.h index 2efa199755..cd668fbc1d 100644 --- a/libstdc++-v3/include/bits/slice_array.h +++ b/libstdc++-v3/include/bits/slice_array.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- slice_array class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 @@ -204,8 +204,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> inline - slice_array<_Tp>::slice_array(const slice_array<_Tp>& a) - : _M_sz(a._M_sz), _M_stride(a._M_stride), _M_array(a._M_array) {} + slice_array<_Tp>::slice_array(const slice_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_stride(__a._M_stride), _M_array(__a._M_array) {} // template<typename _Tp> // inline slice_array<_Tp>::~slice_array () {} diff --git a/libstdc++-v3/include/bits/specfun.h b/libstdc++-v3/include/bits/specfun.h index 77bbda36fd..6dd23d2c4c 100644 --- a/libstdc++-v3/include/bits/specfun.h +++ b/libstdc++-v3/include/bits/specfun.h @@ -1,6 +1,6 @@ // Mathematical Special Functions for -*- C++ -*- -// Copyright (C) 2006-2016 Free Software Foundation, Inc. +// Copyright (C) 2006-2017 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 @@ -38,7 +38,7 @@ #define __cpp_lib_math_special_functions 201603L -#if __STDCPP_WANT_MATH_SPEC_FUNCS__ == 0 +#if __cplusplus <= 201403L && __STDCPP_WANT_MATH_SPEC_FUNCS__ == 0 # error include <cmath> and define __STDCPP_WANT_MATH_SPEC_FUNCS__ #endif @@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @subsection promotion Argument Promotion * The arguments suppled to the non-suffixed functions will be promoted * according to the following rules: - * 1. If any argument intended to be floating opint is given an integral value + * 1. If any argument intended to be floating point is given an integral value * That integral value is promoted to double. * 2. All floating point arguments are promoted up to the largest floating * point precision among them. diff --git a/libstdc++-v3/include/bits/sstream.tcc b/libstdc++-v3/include/bits/sstream.tcc index 59366203ff..72e8742b4c 100644 --- a/libstdc++-v3/include/bits/sstream.tcc +++ b/libstdc++-v3/include/bits/sstream.tcc @@ -1,6 +1,6 @@ // String based streams -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/std_abs.h b/libstdc++-v3/include/bits/std_abs.h new file mode 100644 index 0000000000..1f4a2cadd1 --- /dev/null +++ b/libstdc++-v3/include/bits/std_abs.h @@ -0,0 +1,110 @@ +// -*- C++ -*- C library enhancements header. + +// Copyright (C) 2016-2017 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 include/bits/std_abs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cmath, cstdlib} + */ + +#ifndef _GLIBCXX_BITS_STD_ABS_H +#define _GLIBCXX_BITS_STD_ABS_H + +#pragma GCC system_header + +#include <bits/c++config.h> + +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next <stdlib.h> +#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO +# include_next <math.h> +#endif +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS + +#undef abs + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::abs; + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline long + abs(long __i) { return __builtin_labs(__i); } +#endif + +#ifdef _GLIBCXX_USE_LONG_LONG + inline long long + abs(long long __x) { return __builtin_llabs (__x); } +#endif + +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 2192. Validity and return type of std::abs(0u) is unclear +// 2294. <cstdlib> should declare abs(double) + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR double + abs(double __x) + { return __builtin_fabs(__x); } + + inline _GLIBCXX_CONSTEXPR float + abs(float __x) + { return __builtin_fabsf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + abs(long double __x) + { return __builtin_fabsl(__x); } +#endif + +#if defined(__GLIBCXX_TYPE_INT_N_0) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; } +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + inline _GLIBCXX_CONSTEXPR + __float128 + abs(__float128 __x) + { return __x < 0 ? -__x : __x; } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} + +#endif // _GLIBCXX_BITS_STD_ABS_H diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h new file mode 100644 index 0000000000..b393a94481 --- /dev/null +++ b/libstdc++-v3/include/bits/std_function.h @@ -0,0 +1,811 @@ +// Implementation of std::function -*- C++ -*- + +// Copyright (C) 2004-2017 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 include/bits/function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_STD_FUNCTION_H +#define _GLIBCXX_STD_FUNCTION_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include <bits/c++0x_warning.h> +#else + +#if __cpp_rtti +# include <typeinfo> +#endif +#include <bits/stl_function.h> +#include <bits/invoke.h> +#include <bits/refwrap.h> +#include <bits/functexcept.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * Derives from @c unary_function or @c binary_function, or perhaps + * nothing, depending on the number of arguments provided. The + * primary template is the basis case, which derives nothing. + */ + template<typename _Res, typename... _ArgTypes> + struct _Maybe_unary_or_binary_function { }; + + /// Derives from @c unary_function, as appropriate. + template<typename _Res, typename _T1> + struct _Maybe_unary_or_binary_function<_Res, _T1> + : std::unary_function<_T1, _Res> { }; + + /// Derives from @c binary_function, as appropriate. + template<typename _Res, typename _T1, typename _T2> + struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> + : std::binary_function<_T1, _T2, _Res> { }; + + + /** + * @brief Exception class thrown when class template function's + * operator() is called with an empty target. + * @ingroup exceptions + */ + class bad_function_call : public std::exception + { + public: + virtual ~bad_function_call() noexcept; + + const char* what() const noexcept; + }; + + /** + * Trait identifying "location-invariant" types, meaning that the + * address of the object (or any of its members) will not escape. + * Trivially copyable types are location-invariant and users can + * specialize this trait for other types. + */ + template<typename _Tp> + struct __is_location_invariant + : is_trivially_copyable<_Tp>::type + { }; + + class _Undefined_class; + + union _Nocopy_types + { + void* _M_object; + const void* _M_const_object; + void (*_M_function_pointer)(); + void (_Undefined_class::*_M_member_pointer)(); + }; + + union [[gnu::may_alias]] _Any_data + { + void* _M_access() { return &_M_pod_data[0]; } + const void* _M_access() const { return &_M_pod_data[0]; } + + template<typename _Tp> + _Tp& + _M_access() + { return *static_cast<_Tp*>(_M_access()); } + + template<typename _Tp> + const _Tp& + _M_access() const + { return *static_cast<const _Tp*>(_M_access()); } + + _Nocopy_types _M_unused; + char _M_pod_data[sizeof(_Nocopy_types)]; + }; + + enum _Manager_operation + { + __get_type_info, + __get_functor_ptr, + __clone_functor, + __destroy_functor + }; + + // Simple type wrapper that helps avoid annoying const problems + // when casting between void pointers and pointers-to-pointers. + template<typename _Tp> + struct _Simple_type_wrapper + { + _Simple_type_wrapper(_Tp __value) : __value(__value) { } + + _Tp __value; + }; + + template<typename _Tp> + struct __is_location_invariant<_Simple_type_wrapper<_Tp> > + : __is_location_invariant<_Tp> + { }; + + template<typename _Signature> + class function; + + /// Base class of all polymorphic function object wrappers. + class _Function_base + { + public: + static const std::size_t _M_max_size = sizeof(_Nocopy_types); + static const std::size_t _M_max_align = __alignof__(_Nocopy_types); + + template<typename _Functor> + class _Base_manager + { + protected: + static const bool __stored_locally = + (__is_location_invariant<_Functor>::value + && sizeof(_Functor) <= _M_max_size + && __alignof__(_Functor) <= _M_max_align + && (_M_max_align % __alignof__(_Functor) == 0)); + + typedef integral_constant<bool, __stored_locally> _Local_storage; + + // Retrieve a pointer to the function object + static _Functor* + _M_get_pointer(const _Any_data& __source) + { + const _Functor* __ptr = + __stored_locally? std::__addressof(__source._M_access<_Functor>()) + /* have stored a pointer */ : __source._M_access<_Functor*>(); + return const_cast<_Functor*>(__ptr); + } + + // Clone a location-invariant function object that fits within + // an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, true_type) + { + ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>()); + } + + // Clone a function object that is not location-invariant or + // that cannot fit into an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, false_type) + { + __dest._M_access<_Functor*>() = + new _Functor(*__source._M_access<_Functor*>()); + } + + // Destroying a location-invariant object may still require + // destruction. + static void + _M_destroy(_Any_data& __victim, true_type) + { + __victim._M_access<_Functor>().~_Functor(); + } + + // Destroying an object located on the heap. + static void + _M_destroy(_Any_data& __victim, false_type) + { + delete __victim._M_access<_Functor*>(); + } + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access<const type_info*>() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = _M_get_pointer(__source); + break; + + case __clone_functor: + _M_clone(__dest, __source, _Local_storage()); + break; + + case __destroy_functor: + _M_destroy(__dest, _Local_storage()); + break; + } + return false; + } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f) + { _M_init_functor(__functor, std::move(__f), _Local_storage()); } + + template<typename _Signature> + static bool + _M_not_empty_function(const function<_Signature>& __f) + { return static_cast<bool>(__f); } + + template<typename _Tp> + static bool + _M_not_empty_function(_Tp* __fp) + { return __fp != nullptr; } + + template<typename _Class, typename _Tp> + static bool + _M_not_empty_function(_Tp _Class::* __mp) + { return __mp != nullptr; } + + template<typename _Tp> + static bool + _M_not_empty_function(const _Tp&) + { return true; } + + private: + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type) + { ::new (__functor._M_access()) _Functor(std::move(__f)); } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type) + { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } + }; + + _Function_base() : _M_manager(nullptr) { } + + ~_Function_base() + { + if (_M_manager) + _M_manager(_M_functor, _M_functor, __destroy_functor); + } + + bool _M_empty() const { return !_M_manager; } + + typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, + _Manager_operation); + + _Any_data _M_functor; + _Manager_type _M_manager; + }; + + template<typename _Signature, typename _Functor> + class _Function_handler; + + template<typename _Res, typename _Functor, typename... _ArgTypes> + class _Function_handler<_Res(_ArgTypes...), _Functor> + : public _Function_base::_Base_manager<_Functor> + { + typedef _Function_base::_Base_manager<_Functor> _Base; + + public: + static _Res + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + return (*_Base::_M_get_pointer(__functor))( + std::forward<_ArgTypes>(__args)...); + } + }; + + template<typename _Functor, typename... _ArgTypes> + class _Function_handler<void(_ArgTypes...), _Functor> + : public _Function_base::_Base_manager<_Functor> + { + typedef _Function_base::_Base_manager<_Functor> _Base; + + public: + static void + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + (*_Base::_M_get_pointer(__functor))( + std::forward<_ArgTypes>(__args)...); + } + }; + + template<typename _Class, typename _Member, typename _Res, + typename... _ArgTypes> + class _Function_handler<_Res(_ArgTypes...), _Member _Class::*> + : public _Function_handler<void(_ArgTypes...), _Member _Class::*> + { + typedef _Function_handler<void(_ArgTypes...), _Member _Class::*> + _Base; + + public: + static _Res + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + return std::__invoke(_Base::_M_get_pointer(__functor)->__value, + std::forward<_ArgTypes>(__args)...); + } + }; + + template<typename _Class, typename _Member, typename... _ArgTypes> + class _Function_handler<void(_ArgTypes...), _Member _Class::*> + : public _Function_base::_Base_manager< + _Simple_type_wrapper< _Member _Class::* > > + { + typedef _Member _Class::* _Functor; + typedef _Simple_type_wrapper<_Functor> _Wrapper; + typedef _Function_base::_Base_manager<_Wrapper> _Base; + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access<const type_info*>() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = + &_Base::_M_get_pointer(__source)->__value; + break; + + default: + _Base::_M_manager(__dest, __source, __op); + } + return false; + } + + static void + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + std::__invoke(_Base::_M_get_pointer(__functor)->__value, + std::forward<_ArgTypes>(__args)...); + } + }; + + template<typename _From, typename _To> + using __check_func_return_type + = __or_<is_void<_To>, is_same<_From, _To>, is_convertible<_From, _To>>; + + /** + * @brief Primary class template for std::function. + * @ingroup functors + * + * Polymorphic function wrapper. + */ + template<typename _Res, typename... _ArgTypes> + class function<_Res(_ArgTypes...)> + : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, + private _Function_base + { + template<typename _Func, + typename _Res2 = typename result_of<_Func&(_ArgTypes...)>::type> + struct _Callable : __check_func_return_type<_Res2, _Res> { }; + + // Used so the return type convertibility checks aren't done when + // performing overload resolution for copy construction/assignment. + template<typename _Tp> + struct _Callable<function, _Tp> : false_type { }; + + template<typename _Cond, typename _Tp> + using _Requires = typename enable_if<_Cond::value, _Tp>::type; + + public: + typedef _Res result_type; + + // [3.7.2.1] construct/copy/destroy + + /** + * @brief Default construct creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function() noexcept + : _Function_base() { } + + /** + * @brief Creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function(nullptr_t) noexcept + : _Function_base() { } + + /** + * @brief %Function copy constructor. + * @param __x A %function object with identical call signature. + * @post @c bool(*this) == bool(__x) + * + * The newly-created %function contains a copy of the target of @a + * __x (if it has one). + */ + function(const function& __x); + + /** + * @brief %Function move constructor. + * @param __x A %function object rvalue with identical call signature. + * + * The newly-created %function contains the target of @a __x + * (if it has one). + */ + function(function&& __x) : _Function_base() + { + __x.swap(*this); + } + + /** + * @brief Builds a %function that targets a copy of the incoming + * function object. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * + * The newly-created %function object will target a copy of + * @a __f. If @a __f is @c reference_wrapper<F>, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, the newly-created object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper<F>, this function will not throw. + */ + template<typename _Functor, + typename = _Requires<__not_<is_same<_Functor, function>>, void>, + typename = _Requires<_Callable<_Functor>, void>> + function(_Functor); + + /** + * @brief %Function assignment operator. + * @param __x A %function with identical call signature. + * @post @c (bool)*this == (bool)x + * @returns @c *this + * + * The target of @a __x is copied to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(const function& __x) + { + function(__x).swap(*this); + return *this; + } + + /** + * @brief %Function move-assignment operator. + * @param __x A %function rvalue with identical call signature. + * @returns @c *this + * + * The target of @a __x is moved to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(function&& __x) + { + function(std::move(__x)).swap(*this); + return *this; + } + + /** + * @brief %Function assignment to zero. + * @post @c !(bool)*this + * @returns @c *this + * + * The target of @c *this is deallocated, leaving it empty. + */ + function& + operator=(nullptr_t) noexcept + { + if (_M_manager) + { + _M_manager(_M_functor, _M_functor, __destroy_functor); + _M_manager = nullptr; + _M_invoker = nullptr; + } + return *this; + } + + /** + * @brief %Function assignment to a new target. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * @return @c *this + * + * This %function object wrapper will target a copy of @a + * __f. If @a __f is @c reference_wrapper<F>, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, @c this object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper<F>, this function will not throw. + */ + template<typename _Functor> + _Requires<_Callable<typename decay<_Functor>::type>, function&> + operator=(_Functor&& __f) + { + function(std::forward<_Functor>(__f)).swap(*this); + return *this; + } + + /// @overload + template<typename _Functor> + function& + operator=(reference_wrapper<_Functor> __f) noexcept + { + function(__f).swap(*this); + return *this; + } + + // [3.7.2.2] function modifiers + + /** + * @brief Swap the targets of two %function objects. + * @param __x A %function with identical call signature. + * + * Swap the targets of @c this function object and @a __f. This + * function will not throw an %exception. + */ + void swap(function& __x) noexcept + { + std::swap(_M_functor, __x._M_functor); + std::swap(_M_manager, __x._M_manager); + std::swap(_M_invoker, __x._M_invoker); + } + + // [3.7.2.3] function capacity + + /** + * @brief Determine if the %function wrapper has a target. + * + * @return @c true when this %function object contains a target, + * or @c false when it is empty. + * + * This function will not throw an %exception. + */ + explicit operator bool() const noexcept + { return !_M_empty(); } + + // [3.7.2.4] function invocation + + /** + * @brief Invokes the function targeted by @c *this. + * @returns the result of the target. + * @throws bad_function_call when @c !(bool)*this + * + * The function call operator invokes the target function object + * stored by @c this. + */ + _Res operator()(_ArgTypes... __args) const; + +#if __cpp_rtti + // [3.7.2.5] function target access + /** + * @brief Determine the type of the target of this function object + * wrapper. + * + * @returns the type identifier of the target function object, or + * @c typeid(void) if @c !(bool)*this. + * + * This function will not throw an %exception. + */ + const type_info& target_type() const noexcept; + + /** + * @brief Access the stored target function object. + * + * @return Returns a pointer to the stored target function object, + * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL + * pointer. + * + * This function does not throw exceptions. + * + * @{ + */ + template<typename _Functor> _Functor* target() noexcept; + + template<typename _Functor> const _Functor* target() const noexcept; + // @} +#endif + + private: + using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...); + _Invoker_type _M_invoker; + }; + +#if __cpp_deduction_guides >= 201606 + template<typename> + struct __function_guide_helper + { }; + + template<typename _Res, typename _Tp, bool _Nx, typename... _Args> + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template<typename _Res, typename _Tp, bool _Nx, typename... _Args> + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template<typename _Res, typename _Tp, bool _Nx, typename... _Args> + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template<typename _Res, typename _Tp, bool _Nx, typename... _Args> + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template<typename _Res, typename... _ArgTypes> + function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>; + + template<typename _Functor, typename _Signature = typename + __function_guide_helper<decltype(&_Functor::operator())>::type> + function(_Functor) -> function<_Signature>; +#endif + + // Out-of-line member definitions. + template<typename _Res, typename... _ArgTypes> + function<_Res(_ArgTypes...)>:: + function(const function& __x) + : _Function_base() + { + if (static_cast<bool>(__x)) + { + __x._M_manager(_M_functor, __x._M_functor, __clone_functor); + _M_invoker = __x._M_invoker; + _M_manager = __x._M_manager; + } + } + + template<typename _Res, typename... _ArgTypes> + template<typename _Functor, typename, typename> + function<_Res(_ArgTypes...)>:: + function(_Functor __f) + : _Function_base() + { + typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler; + + if (_My_handler::_M_not_empty_function(__f)) + { + _My_handler::_M_init_functor(_M_functor, std::move(__f)); + _M_invoker = &_My_handler::_M_invoke; + _M_manager = &_My_handler::_M_manager; + } + } + + template<typename _Res, typename... _ArgTypes> + _Res + function<_Res(_ArgTypes...)>:: + operator()(_ArgTypes... __args) const + { + if (_M_empty()) + __throw_bad_function_call(); + return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); + } + +#if __cpp_rtti + template<typename _Res, typename... _ArgTypes> + const type_info& + function<_Res(_ArgTypes...)>:: + target_type() const noexcept + { + if (_M_manager) + { + _Any_data __typeinfo_result; + _M_manager(__typeinfo_result, _M_functor, __get_type_info); + return *__typeinfo_result._M_access<const type_info*>(); + } + else + return typeid(void); + } + + template<typename _Res, typename... _ArgTypes> + template<typename _Functor> + _Functor* + function<_Res(_ArgTypes...)>:: + target() noexcept + { + const function* __const_this = this; + const _Functor* __func = __const_this->template target<_Functor>(); + return const_cast<_Functor*>(__func); + } + + template<typename _Res, typename... _ArgTypes> + template<typename _Functor> + const _Functor* + function<_Res(_ArgTypes...)>:: + target() const noexcept + { + if (typeid(_Functor) == target_type() && _M_manager) + { + _Any_data __ptr; + _M_manager(__ptr, _M_functor, __get_functor_ptr); + return __ptr._M_access<const _Functor*>(); + } + else + return nullptr; + } +#endif + + // [20.7.15.2.6] null pointer comparisons + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c true if the wrapper has no target, @c false otherwise + * + * This function will not throw an %exception. + */ + template<typename _Res, typename... _Args> + inline bool + operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return !static_cast<bool>(__f); } + + /// @overload + template<typename _Res, typename... _Args> + inline bool + operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return !static_cast<bool>(__f); } + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c false if the wrapper has no target, @c true otherwise + * + * This function will not throw an %exception. + */ + template<typename _Res, typename... _Args> + inline bool + operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return static_cast<bool>(__f); } + + /// @overload + template<typename _Res, typename... _Args> + inline bool + operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return static_cast<bool>(__f); } + + + // [20.7.15.2.7] specialized algorithms + + /** + * @brief Swap the targets of two polymorphic function object wrappers. + * + * This function will not throw an %exception. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps + template<typename _Res, typename... _Args> + inline void + swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_STD_FUNCTION_H diff --git a/libstdc++-v3/include/bits/std_mutex.h b/libstdc++-v3/include/bits/std_mutex.h index 49ef752a4e..17d55f5576 100644 --- a/libstdc++-v3/include/bits/std_mutex.h +++ b/libstdc++-v3/include/bits/std_mutex.h @@ -1,6 +1,6 @@ // std::mutex implementation -*- C++ -*- -// Copyright (C) 2003-2016 Free Software Foundation, Inc. +// Copyright (C) 2003-2017 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 @@ -122,7 +122,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } native_handle_type - native_handle() + native_handle() noexcept { return &_M_mutex; } }; @@ -139,13 +139,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct adopt_lock_t { explicit adopt_lock_t() = default; }; /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. - constexpr defer_lock_t defer_lock { }; + _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; /// Tag used to prevent a scoped lock from blocking if a mutex is locked. - constexpr try_to_lock_t try_to_lock { }; + _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; /// Tag used to make a scoped lock take ownership of a locked mutex. - constexpr adopt_lock_t adopt_lock { }; + _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; /** @brief A simple scoped lock type. * @@ -161,7 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit lock_guard(mutex_type& __m) : _M_device(__m) { _M_device.lock(); } - lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m) + lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) { } // calling thread owns mutex ~lock_guard() @@ -206,7 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) { } - unique_lock(mutex_type& __m, adopt_lock_t) + unique_lock(mutex_type& __m, adopt_lock_t) noexcept : _M_device(std::__addressof(__m)), _M_owns(true) { // XXX calling thread owns mutex diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index c2ac0317f1..2cd5303a10 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -1,6 +1,6 @@ // Algorithm implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -583,6 +583,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Predicate __pred) { __first = std::find_if_not(__first, __last, __pred); + if (__first == __last) + return true; + ++__first; return std::none_of(__first, __last, __pred); } @@ -3698,10 +3701,80 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__is_permutation(__first1, __last1, __first2, __last2, __gnu_cxx::__ops::__iter_comp_iter(__pred)); } -#endif + +#if __cplusplus > 201402L + +#define __cpp_lib_clamp 201603 + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise. + */ + template<typename _Tp> + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) + { + __glibcxx_assert(!(__hi < __lo)); + return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val; + } + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @param __comp A comparison functor. + * @return max(__val, __lo, __comp) if __comp(__val, __hi) + * or min(__val, __hi, __comp) otherwise. + */ + template<typename _Tp, typename _Compare> + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) + { + __glibcxx_assert(!__comp(__hi, __lo)); + return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val; + } +#endif // C++17 +#endif // C++14 #ifdef _GLIBCXX_USE_C99_STDINT_TR1 /** + * @brief Generate two uniformly distributed integers using a + * single distribution invocation. + * @param __b0 The upper bound for the first integer. + * @param __b1 The upper bound for the second integer. + * @param __g A UniformRandomBitGenerator. + * @return A pair (i, j) with i and j uniformly distributed + * over [0, __b0) and [0, __b1), respectively. + * + * Requires: __b0 * __b1 <= __g.max() - __g.min(). + * + * Using uniform_int_distribution with a range that is very + * small relative to the range of the generator ends up wasting + * potentially expensively generated randomness, since + * uniform_int_distribution does not store leftover randomness + * between invocations. + * + * If we know we want two integers in ranges that are sufficiently + * small, we can compose the ranges, use a single distribution + * invocation, and significantly reduce the waste. + */ + template<typename _IntType, typename _UniformRandomBitGenerator> + pair<_IntType, _IntType> + __gen_two_uniform_ints(_IntType __b0, _IntType __b1, + _UniformRandomBitGenerator&& __g) + { + _IntType __x + = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); + return std::make_pair(__x / __b1, __x % __b1); + } + + /** * @brief Shuffle the elements of a sequence using a uniform random * number generator. * @ingroup mutating_algorithms @@ -3733,6 +3806,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename std::make_unsigned<_DistanceType>::type __ud_type; typedef typename std::uniform_int_distribution<__ud_type> __distr_type; typedef typename __distr_type::param_type __p_type; + + typedef typename remove_reference<_UniformRandomNumberGenerator>::type + _Gen; + typedef typename common_type<typename _Gen::result_type, __ud_type>::type + __uc_type; + + const __uc_type __urngrange = __g.max() - __g.min(); + const __uc_type __urange = __uc_type(__last - __first); + + if (__urngrange / __urange >= __urange) + // I.e. (__urngrange >= __urange * __urange) but without wrap issues. + { + _RandomAccessIterator __i = __first + 1; + + // Since we know the range isn't empty, an even number of elements + // means an uneven number of elements /to swap/, in which case we + // do the first one up front: + + if ((__urange % 2) == 0) + { + __distr_type __d{0, 1}; + std::iter_swap(__i++, __first + __d(__g)); + } + + // Now we know that __last - __i is even, so we do the rest in pairs, + // using a single distribution invocation to produce swap positions + // for two successive elements at a time: + + while (__i != __last) + { + const __uc_type __swap_range = __uc_type(__i - __first) + 1; + + const pair<__uc_type, __uc_type> __pospos = + __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); + + std::iter_swap(__i++, __first + __pospos.first); + std::iter_swap(__i++, __first + __pospos.second); + } + + return; + } + __distr_type __d; for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) @@ -3752,7 +3867,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO * @param __first An input iterator. * @param __last An input iterator. * @param __f A unary function object. - * @return @p __f (std::move(@p __f) in C++0x). + * @return @p __f * * Applies the function object @p __f to each element in the range * @p [first,last). @p __f must not modify the order of the sequence. @@ -3767,7 +3882,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); for (; __first != __last; ++__first) __f(*__first); - return _GLIBCXX_MOVE(__f); + return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant. } /** @@ -5576,6 +5691,130 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __gnu_cxx::__ops::__iter_comp_iter(__comp)); } +#if __cplusplus >= 201402L + /// Reservoir sampling algorithm. + template<typename _InputIterator, typename _RandomAccessIterator, + typename _Size, typename _UniformRandomBitGenerator> + _RandomAccessIterator + __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, + _RandomAccessIterator __out, random_access_iterator_tag, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + _Size __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + + /// Selection sampling algorithm. + template<typename _ForwardIterator, typename _OutputIterator, typename _Cat, + typename _Size, typename _UniformRandomBitGenerator> + _OutputIterator + __sample(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag, + _OutputIterator __out, _Cat, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + using _USize = make_unsigned_t<_Size>; + using _Gen = remove_reference_t<_UniformRandomBitGenerator>; + using __uc_type = common_type_t<typename _Gen::result_type, _USize>; + + __distrib_type __d{}; + _Size __unsampled_sz = std::distance(__first, __last); + __n = std::min(__n, __unsampled_sz); + + // If possible, we use __gen_two_uniform_ints to efficiently produce + // two random numbers using a single distribution invocation: + + const __uc_type __urngrange = __g.max() - __g.min(); + if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) + // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without + // wrapping issues. + { + while (__n != 0 && __unsampled_sz >= 2) + { + const pair<_Size, _Size> __p = + __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); + + --__unsampled_sz; + if (__p.first < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + + if (__n == 0) break; + + --__unsampled_sz; + if (__p.second < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + } + } + + // The loop above is otherwise equivalent to this one-at-a-time version: + + for (; __n != 0; ++__first) + if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) + { + *__out++ = *__first; + --__n; + } + return __out; + } + +#if __cplusplus > 201402L +#define __cpp_lib_sample 201603 + /// Take a random sample from a population. + template<typename _PopulationIterator, typename _SampleIterator, + typename _Distance, typename _UniformRandomBitGenerator> + _SampleIterator + sample(_PopulationIterator __first, _PopulationIterator __last, + _SampleIterator __out, _Distance __n, + _UniformRandomBitGenerator&& __g) + { + using __pop_cat = typename + std::iterator_traits<_PopulationIterator>::iterator_category; + using __samp_cat = typename + std::iterator_traits<_SampleIterator>::iterator_category; + + static_assert( + __or_<is_convertible<__pop_cat, forward_iterator_tag>, + is_convertible<__samp_cat, random_access_iterator_tag>>::value, + "output range must use a RandomAccessIterator when input range" + " does not meet the ForwardIterator requirements"); + + static_assert(is_integral<_Distance>::value, + "sample size must be an integer type"); + + typename iterator_traits<_PopulationIterator>::difference_type __d = __n; + return std::__sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, + __d, std::forward<_UniformRandomBitGenerator>(__g)); + } +#endif // C++17 +#endif // C++14 + _GLIBCXX_END_NAMESPACE_ALGO } // namespace std diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 210b173454..ea7cd21023 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -1,6 +1,6 @@ // Core algorithmic facilities -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 629fe4dd90..37e000ad96 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -1,6 +1,6 @@ // vector<bool> specialization -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -500,6 +500,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Bit_alloc_traits::deallocate(_M_impl, _M_impl._M_end_of_storage - __n, __n); + _M_impl._M_start = _M_impl._M_finish = _Bit_iterator(); + _M_impl._M_end_of_storage = _Bit_pointer(); } } @@ -1054,9 +1056,18 @@ template<typename _Alloc> #if __cplusplus >= 201103L template<typename... _Args> +#if __cplusplus > 201402L + reference +#else void +#endif emplace_back(_Args&&... __args) - { push_back(bool(__args...)); } + { + push_back(bool(__args...)); +#if __cplusplus > 201402L + return back(); +#endif + } template<typename... _Args> iterator diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 3d126288d8..c1504e9bcb 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -1,6 +1,6 @@ // nonstandard construct and destroy functions -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -84,6 +84,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif + template<typename _T1> + inline void + _Construct_novalue(_T1* __p) + { ::new(static_cast<void*>(__p)) _T1; } + /** * Destroy the object pointed to by a pointer type. */ @@ -127,6 +132,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __destroy(__first, __last); } + template<bool> + struct _Destroy_n_aux + { + template<typename _ForwardIterator, typename _Size> + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } + }; + + template<> + struct _Destroy_n_aux<true> + { + template<typename _ForwardIterator, typename _Size> + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + std::advance(__first, __count); + return __first; + } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template<typename _ForwardIterator, typename _Size> + inline _ForwardIterator + _Destroy_n(_ForwardIterator __first, _Size __count) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; + return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + __destroy_n(__first, __count); + } + /** * Destroy a range of objects using the supplied allocator. For * nondefault allocators we do not optimize away invocation of diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index d7a9d523e3..6090635b7d 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -1,6 +1,6 @@ // Deque implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -63,6 +63,8 @@ #include <initializer_list> #endif +#include <debug/assertions.h> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER @@ -106,10 +108,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct _Deque_iterator { #if __cplusplus < 201103L - typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - typedef _Tp* _Elt_pointer; - typedef _Tp** _Map_pointer; + typedef _Tp* _Elt_pointer; + typedef _Tp** _Map_pointer; #else private: template<typename _Up> @@ -126,13 +128,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT { return __deque_buf_size(sizeof(_Tp)); } - typedef std::random_access_iterator_tag iterator_category; - typedef _Tp value_type; - typedef _Ptr pointer; - typedef _Ref reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Deque_iterator _Self; + typedef std::random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Deque_iterator _Self; _Elt_pointer _M_cur; _Elt_pointer _M_first; @@ -141,14 +143,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT : _M_cur(__x), _M_first(*__y), - _M_last(*__y + _S_buffer_size()), _M_node(__y) { } + _M_last(*__y + _S_buffer_size()), _M_node(__y) { } _Deque_iterator() _GLIBCXX_NOEXCEPT : _M_cur(), _M_first(), _M_last(), _M_node() { } _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) { } + _M_last(__x._M_last), _M_node(__x._M_node) { } iterator _M_const_cast() const _GLIBCXX_NOEXCEPT @@ -212,7 +214,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const difference_type __node_offset = __offset > 0 ? __offset / difference_type(_S_buffer_size()) - : -difference_type((-__offset - 1) + : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; _M_set_node(_M_node + __node_offset); _M_cur = _M_first + (__offset - __node_offset @@ -243,7 +245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator[](difference_type __n) const _GLIBCXX_NOEXCEPT { return *(*this + __n); } - /** + /** * Prepares to traverse new_node. Sets everything except * _M_cur, which should therefore be set by the caller * immediately afterwards, based on _M_first and _M_last. @@ -291,7 +293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur) - : (__x._M_node < __y._M_node); } + : (__x._M_node < __y._M_node); } template<typename _Tp, typename _RefL, typename _PtrL, typename _RefR, typename _PtrR> @@ -299,7 +301,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur) - : (__x._M_node < __y._M_node); } + : (__x._M_node < __y._M_node); } template<typename _Tp, typename _Ref, typename _Ptr> inline bool @@ -475,14 +477,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; public: - typedef _Alloc allocator_type; + typedef _Alloc allocator_type; typedef typename _Alloc_traits::size_type size_type; allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_get_Tp_allocator()); } - typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; + typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator; _Deque_base() @@ -595,7 +597,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Ptr _M_allocate_node() - { + { typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); } @@ -828,12 +830,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class deque : protected _Deque_base<_Tp, _Alloc> { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -#if __cplusplus < 201103L + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -#endif +# endif __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif typedef _Deque_base<_Tp, _Alloc> _Base; typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; @@ -841,18 +845,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Base::_Map_pointer _Map_pointer; public: - 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 typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; + 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 typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; protected: static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT @@ -868,7 +872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER using _Base::_M_deallocate_map; using _Base::_M_get_Tp_allocator; - /** + /** * A total of four data members accumulated down the hierarchy. * May be accessed via _M_impl.* */ @@ -937,13 +941,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief %Deque copy constructor. * @param __x A %deque of identical element and allocator types. * - * The newly-created %deque uses a copy of the allocation object used - * by @a __x. + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). */ deque(const deque& __x) : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()), __x.size()) - { std::__uninitialized_copy_a(__x.begin(), __x.end(), + { std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, _M_get_Tp_allocator()); } @@ -1016,16 +1020,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - deque(_InputIterator __first, _InputIterator __last, + deque(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { _M_initialize_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - deque(_InputIterator __first, _InputIterator __last, + deque(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_initialize_dispatch(__first, __last, _Integral()); @@ -1044,8 +1048,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief %Deque assignment operator. * @param __x A %deque of identical element and allocator types. * - * All the elements of @a x are copied, but unlike the copy constructor, - * the allocator object is not copied. + * All the elements of @a x are copied. + * + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). */ deque& operator=(const deque& __x); @@ -1076,12 +1082,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %deque and that the * resulting %deque's size is the same as the number of elements - * assigned. Old data may be lost. + * assigned. */ deque& operator=(initializer_list<value_type> __l) { - this->assign(__l.begin(), __l.end()); + _M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); return *this; } #endif @@ -1094,7 +1101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function fills a %deque with @a n copies of the given * value. Note that the assignment completely changes the * %deque and that the resulting %deque's size is the same as - * the number of elements assigned. Old data may be lost. + * the number of elements assigned. */ void assign(size_type __n, const value_type& __val) @@ -1110,19 +1117,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %deque and that the * resulting %deque's size is the same as the number of elements - * assigned. Old data may be lost. + * assigned. */ #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - void - assign(_InputIterator __first, _InputIterator __last) - { + void + assign(_InputIterator __first, _InputIterator __last) + { typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_assign_dispatch(__first, __last, _Integral()); } @@ -1138,11 +1145,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %deque and that the * resulting %deque's size is the same as the number of elements - * assigned. Old data may be lost. + * assigned. */ void assign(initializer_list<value_type> __l) - { this->assign(__l.begin(), __l.end()); } + { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } #endif /// Get a copy of the memory allocation object. @@ -1306,7 +1313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = size(); if (__new_size > __len) - insert(this->_M_impl._M_finish, __new_size - __len, __x); + _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); else if (__new_size < __len) _M_erase_at_end(this->_M_impl._M_start + difference_type(__new_size)); @@ -1328,7 +1335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = size(); if (__new_size > __len) - insert(this->_M_impl._M_finish, __new_size - __len, __x); + _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); else if (__new_size < __len) _M_erase_at_end(this->_M_impl._M_start + difference_type(__new_size)); @@ -1364,7 +1371,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference operator[](size_type __n) _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start[difference_type(__n)]; } + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } /** * @brief Subscript access to the data contained in the %deque. @@ -1379,7 +1389,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start[difference_type(__n)]; } + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } protected: /// Safety check used only from at(). @@ -1436,7 +1449,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference front() _GLIBCXX_NOEXCEPT - { return *begin(); } + { + __glibcxx_requires_nonempty(); + return *begin(); + } /** * Returns a read-only (constant) reference to the data at the first @@ -1444,7 +1460,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference front() const _GLIBCXX_NOEXCEPT - { return *begin(); } + { + __glibcxx_requires_nonempty(); + return *begin(); + } /** * Returns a read/write reference to the data at the last element of the @@ -1453,6 +1472,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference back() _GLIBCXX_NOEXCEPT { + __glibcxx_requires_nonempty(); iterator __tmp = end(); --__tmp; return *__tmp; @@ -1465,6 +1485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const_reference back() const _GLIBCXX_NOEXCEPT { + __glibcxx_requires_nonempty(); const_iterator __tmp = end(); --__tmp; return *__tmp; @@ -1486,8 +1507,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) { _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur - 1, - __x); + this->_M_impl._M_start._M_cur - 1, + __x); --this->_M_impl._M_start._M_cur; } else @@ -1500,8 +1521,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { emplace_front(std::move(__x)); } template<typename... _Args> - void - emplace_front(_Args&&... __args); +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args); #endif /** @@ -1520,7 +1545,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER != this->_M_impl._M_finish._M_last - 1) { _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, __x); + this->_M_impl._M_finish._M_cur, __x); ++this->_M_impl._M_finish._M_cur; } else @@ -1533,8 +1558,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { emplace_back(std::move(__x)); } template<typename... _Args> - void - emplace_back(_Args&&... __args); +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); #endif /** @@ -1548,11 +1577,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_front() _GLIBCXX_NOEXCEPT { + __glibcxx_requires_nonempty(); if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_last - 1) { _Alloc_traits::destroy(this->_M_impl, - this->_M_impl._M_start._M_cur); + this->_M_impl._M_start._M_cur); ++this->_M_impl._M_start._M_cur; } else @@ -1570,12 +1600,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_back() _GLIBCXX_NOEXCEPT { + __glibcxx_requires_nonempty(); if (this->_M_impl._M_finish._M_cur != this->_M_impl._M_finish._M_first) { --this->_M_impl._M_finish._M_cur; _Alloc_traits::destroy(this->_M_impl, - this->_M_impl._M_finish._M_cur); + this->_M_impl._M_finish._M_cur); } else _M_pop_back_aux(); @@ -1592,8 +1623,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * with T(std::forward<Args>(args)...) before the specified location. */ template<typename... _Args> - iterator - emplace(const_iterator __position, _Args&&... __args); + iterator + emplace(const_iterator __position, _Args&&... __args); /** * @brief Inserts given value into %deque before specified iterator. @@ -1645,7 +1676,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator insert(const_iterator __p, initializer_list<value_type> __l) - { return this->insert(__p, __l.begin(), __l.end()); } + { + auto __offset = __p - cbegin(); + _M_range_insert_aux(__p._M_const_cast(), __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } #endif #if __cplusplus >= 201103L @@ -1695,10 +1731,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - iterator - insert(const_iterator __position, _InputIterator __first, + iterator + insert(const_iterator __position, _InputIterator __first, _InputIterator __last) - { + { difference_type __offset = __position - cbegin(); _M_insert_dispatch(__position._M_const_cast(), __first, __last, __false_type()); @@ -1716,10 +1752,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * by @a __position. This is known as <em>range insert</em>. */ template<typename _InputIterator> - void - insert(iterator __position, _InputIterator __first, + void + insert(iterator __position, _InputIterator __first, _InputIterator __last) - { + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); @@ -1779,10 +1815,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * (Four pointers, so it should be quite fast.) * Note that the global std::swap() function is specialized such that * std::swap(d1,d2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(deque& __x) _GLIBCXX_NOEXCEPT { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif _M_impl._M_swap_data(__x._M_impl); _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); @@ -1806,22 +1848,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) - { + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_initialize_map(static_cast<size_type>(__n)); _M_fill_initialize(__x); } // called by the range constructor to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) - { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_range_initialize(__first, __last, _IterCategory()); + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); } // called by the second initialize_dispatch above @@ -1837,14 +1878,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * push_back on each value from the iterator. */ template<typename _InputIterator> - void - _M_range_initialize(_InputIterator __first, _InputIterator __last, + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, std::input_iterator_tag); // called by the second initialize_dispatch above template<typename _ForwardIterator> - void - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); //@} @@ -1875,40 +1916,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } // called by the range assign to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) - { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_assign_aux(__first, __last, _IterCategory()); - } + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } // called by the second assign_dispatch above template<typename _InputIterator> - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, std::input_iterator_tag); // called by the second assign_dispatch above template<typename _ForwardIterator> - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag) - { + { const size_type __len = std::distance(__first, __last); if (__len > size()) { _ForwardIterator __mid = __first; std::advance(__mid, size()); std::copy(__first, __mid, begin()); - insert(end(), __mid, __last); + _M_range_insert_aux(end(), __mid, __last, + std::__iterator_category(__first)); } else _M_erase_at_end(std::copy(__first, __last, begin())); @@ -1922,7 +1960,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__n > size()) { std::fill(begin(), end(), __val); - insert(end(), __n - size(), __val); + _M_fill_insert(end(), __n - size(), __val); } else { @@ -1939,10 +1977,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_push_front_aux(const value_type&); #else template<typename... _Args> - void _M_push_back_aux(_Args&&... __args); + void _M_push_back_aux(_Args&&... __args); template<typename... _Args> - void _M_push_front_aux(_Args&&... __args); + void _M_push_front_aux(_Args&&... __args); #endif void _M_pop_back_aux(); @@ -1958,33 +1996,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_insert_dispatch(iterator __pos, + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type) - { _M_fill_insert(__pos, __n, __x); } + { _M_fill_insert(__pos, __n, __x); } // called by the range insert to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_insert_dispatch(iterator __pos, + void + _M_insert_dispatch(iterator __pos, _InputIterator __first, _InputIterator __last, __false_type) - { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_range_insert_aux(__pos, __first, __last, _IterCategory()); + { + _M_range_insert_aux(__pos, __first, __last, + std::__iterator_category(__first)); } // called by the second insert_dispatch above template<typename _InputIterator> - void - _M_range_insert_aux(iterator __pos, _InputIterator __first, + void + _M_range_insert_aux(iterator __pos, _InputIterator __first, _InputIterator __last, std::input_iterator_tag); // called by the second insert_dispatch above template<typename _ForwardIterator> - void - _M_range_insert_aux(iterator __pos, _ForwardIterator __first, + void + _M_range_insert_aux(iterator __pos, _ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); // Called by insert(p,n,x), and the range insert when it turns out to be @@ -1999,8 +2036,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_insert_aux(iterator __pos, const value_type& __x); #else template<typename... _Args> - iterator - _M_insert_aux(iterator __pos, _Args&&... __args); + iterator + _M_insert_aux(iterator __pos, _Args&&... __args); #endif // called by insert(p,n,x) via fill_insert @@ -2009,8 +2046,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // called by range_insert_aux for forward iterators template<typename _ForwardIterator> - void - _M_insert_aux(iterator __pos, + void + _M_insert_aux(iterator __pos, _ForwardIterator __first, _ForwardIterator __last, size_type __n); @@ -2023,9 +2060,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by ~deque(). // NB: Doesn't deallocate the nodes. template<typename _Alloc1> - void - _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) - { _M_destroy_data_aux(__first, __last); } + void + _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) + { _M_destroy_data_aux(__first, __last); } void _M_destroy_data(iterator __first, iterator __last, @@ -2076,7 +2113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_reserve_elements_at_front(size_type __n) { const size_type __vacancies = this->_M_impl._M_start._M_cur - - this->_M_impl._M_start._M_first; + - this->_M_impl._M_start._M_first; if (__n > __vacancies) _M_new_elements_at_front(__n - __vacancies); return this->_M_impl._M_start - difference_type(__n); @@ -2196,8 +2233,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { // The rvalue's allocator cannot be moved and is not equal, // so we need to individually move each element. - this->assign(std::__make_move_if_noexcept_iterator(__x.begin()), - std::__make_move_if_noexcept_iterator(__x.end())); + _M_assign_aux(std::__make_move_if_noexcept_iterator(__x.begin()), + std::__make_move_if_noexcept_iterator(__x.end()), + std::random_access_iterator_tag()); __x.clear(); } } @@ -2220,7 +2258,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) { return __x.size() == __y.size() - && std::equal(__x.begin(), __x.end(), __y.begin()); } + && std::equal(__x.begin(), __x.end(), __y.begin()); } /** * @brief Deque ordering relation. diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h index 68f39ff269..4fbcdb91f5 100644 --- a/libstdc++-v3/include/bits/stl_function.h +++ b/libstdc++-v3/include/bits/stl_function.h @@ -1,6 +1,6 @@ // Functor implementations -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -224,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 201103L -#define __cpp_lib_transparent_operators 201210 +#define __cpp_lib_transparent_operators 201510 template<> struct plus<void> diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h index 5b405dbab5..f8cd0c0542 100644 --- a/libstdc++-v3/include/bits/stl_heap.h +++ b/libstdc++-v3/include/bits/stl_heap.h @@ -1,6 +1,6 @@ // Heap implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Compare> _Distance __is_heap_until(_RandomAccessIterator __first, _Distance __n, - _Compare __comp) + _Compare& __comp) { _Distance __parent = 0; for (_Distance __child = 1; __child < __n; ++__child) @@ -91,8 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _Distance __n) { - return std::__is_heap_until(__first, __n, - __gnu_cxx::__ops::__iter_less_iter()) == __n; + __gnu_cxx::__ops::_Iter_less_iter __comp; + return std::__is_heap_until(__first, __n, __comp) == __n; } template<typename _RandomAccessIterator, typename _Compare, @@ -100,8 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) { - return std::__is_heap_until(__first, __n, - __gnu_cxx::__ops::__iter_comp_iter(__comp)) == __n; + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __n, __cmp) == __n; } template<typename _RandomAccessIterator> @@ -113,7 +114,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) - { return std::__is_heap(__first, __comp, std::distance(__first, __last)); } + { + return std::__is_heap(__first, _GLIBCXX_MOVE(__comp), + std::distance(__first, __last)); + } // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap, // + is_heap and is_heap_until in C++0x. @@ -123,7 +127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __topIndex, _Tp __value, - _Compare __comp) + _Compare& __comp) { _Distance __parent = (__holeIndex - 1) / 2; while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) @@ -162,10 +166,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_heap(__first, __last - 1); + __gnu_cxx::__ops::_Iter_less_val __comp; _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), - __gnu_cxx::__ops::__iter_less_val()); + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); } /** @@ -197,10 +201,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_heap_pred(__first, __last - 1, __comp); + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), - __gnu_cxx::__ops::__iter_comp_val(__comp)); + _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); } template<typename _RandomAccessIterator, typename _Distance, @@ -227,15 +232,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + (__secondChild - 1))); __holeIndex = __secondChild - 1; } - std::__push_heap(__first, __holeIndex, __topIndex, - _GLIBCXX_MOVE(__value), - __gnu_cxx::__ops::__iter_comp_val(__comp)); + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + std::__push_heap(__first, __holeIndex, __topIndex, + _GLIBCXX_MOVE(__value), __cmp); } template<typename _RandomAccessIterator, typename _Compare> inline void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _RandomAccessIterator __result, _Compare __comp) + _RandomAccessIterator __result, _Compare& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; @@ -277,8 +283,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { --__last; - std::__pop_heap(__first, __last, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__pop_heap(__first, __last, __last, __comp); } } @@ -308,16 +314,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); --__last; - std::__pop_heap(__first, __last, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__pop_heap(__first, __last, __last, __cmp); } } template<typename _RandomAccessIterator, typename _Compare> void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) + _Compare& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; @@ -360,8 +367,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - std::__make_heap(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__make_heap(__first, __last, __comp); } /** @@ -385,14 +392,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - std::__make_heap(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__make_heap(__first, __last, __cmp); } template<typename _RandomAccessIterator, typename _Compare> void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) + _Compare& __comp) { while (__last - __first > 1) { @@ -422,8 +430,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_heap(__first, __last); - std::__sort_heap(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__sort_heap(__first, __last, __comp); } /** @@ -448,8 +456,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_heap_pred(__first, __last, __comp); - std::__sort_heap(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__sort_heap(__first, __last, __cmp); } #if __cplusplus >= 201103L @@ -475,9 +484,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); + __gnu_cxx::__ops::_Iter_less_iter __comp; return __first + - std::__is_heap_until(__first, std::distance(__first, __last), - __gnu_cxx::__ops::__iter_less_iter()); + std::__is_heap_until(__first, std::distance(__first, __last), __comp); } /** @@ -502,9 +511,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); return __first - + std::__is_heap_until(__first, std::distance(__first, __last), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); } /** @@ -531,7 +541,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) - { return std::is_heap_until(__first, __last, __comp) == __last; } + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + const auto __dist = std::distance(__first, __last); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __dist, __cmp) == __dist; + } #endif _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 3401cd0fb7..e6ef784ce1 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1,6 +1,6 @@ // Iterators -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -65,6 +65,10 @@ #include <bits/move.h> #include <bits/ptr_traits.h> +#if __cplusplus > 201402L +# define __cpp_lib_array_constexpr 201603 +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -118,17 +122,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ // _GLIBCXX_RESOLVE_LIB_DEFECTS // 235 No specification of default ctor for reverse_iterator + _GLIBCXX17_CONSTEXPR reverse_iterator() : current() { } /** * This %iterator will move in the opposite direction that @p x does. */ - explicit + explicit _GLIBCXX17_CONSTEXPR reverse_iterator(iterator_type __x) : current(__x) { } /** * The copy constructor is normal. */ + _GLIBCXX17_CONSTEXPR reverse_iterator(const reverse_iterator& __x) : current(__x.current) { } @@ -137,13 +143,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * underlying %iterator can be converted to the type of @c current. */ template<typename _Iter> + _GLIBCXX17_CONSTEXPR reverse_iterator(const reverse_iterator<_Iter>& __x) : current(__x.base()) { } /** * @return @c current, the %iterator used for underlying work. */ - iterator_type + _GLIBCXX17_CONSTEXPR iterator_type base() const { return current; } @@ -157,7 +164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c *x remains valid after @c x has been modified or * destroyed. This is a bug: http://gcc.gnu.org/PR51823 */ - reference + _GLIBCXX17_CONSTEXPR reference operator*() const { _Iterator __tmp = current; @@ -169,7 +176,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * This requires that @c --current is dereferenceable. */ - pointer + _GLIBCXX17_CONSTEXPR pointer operator->() const { return &(operator*()); } @@ -178,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Decrements the underlying iterator. */ - reverse_iterator& + _GLIBCXX17_CONSTEXPR reverse_iterator& operator++() { --current; @@ -190,7 +197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Decrements the underlying iterator. */ - reverse_iterator + _GLIBCXX17_CONSTEXPR reverse_iterator operator++(int) { reverse_iterator __tmp = *this; @@ -203,7 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Increments the underlying iterator. */ - reverse_iterator& + _GLIBCXX17_CONSTEXPR reverse_iterator& operator--() { ++current; @@ -215,7 +222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Increments the underlying iterator. */ - reverse_iterator + _GLIBCXX17_CONSTEXPR reverse_iterator operator--(int) { reverse_iterator __tmp = *this; @@ -228,7 +235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The underlying iterator must be a Random Access Iterator. */ - reverse_iterator + _GLIBCXX17_CONSTEXPR reverse_iterator operator+(difference_type __n) const { return reverse_iterator(current - __n); } @@ -238,7 +245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Moves the underlying iterator backwards @a __n steps. * The underlying iterator must be a Random Access Iterator. */ - reverse_iterator& + _GLIBCXX17_CONSTEXPR reverse_iterator& operator+=(difference_type __n) { current -= __n; @@ -250,7 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The underlying iterator must be a Random Access Iterator. */ - reverse_iterator + _GLIBCXX17_CONSTEXPR reverse_iterator operator-(difference_type __n) const { return reverse_iterator(current + __n); } @@ -260,7 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Moves the underlying iterator forwards @a __n steps. * The underlying iterator must be a Random Access Iterator. */ - reverse_iterator& + _GLIBCXX17_CONSTEXPR reverse_iterator& operator-=(difference_type __n) { current += __n; @@ -272,7 +279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The underlying iterator must be a Random Access Iterator. */ - reference + _GLIBCXX17_CONSTEXPR reference operator[](difference_type __n) const { return *(*this + __n); } }; @@ -288,110 +295,113 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * */ template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator==(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return __x.base() == __y.base(); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return __y.base() < __x.base(); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator!=(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return !(__x == __y); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return __y < __x; } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<=(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return !(__y < __x); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>=(const reverse_iterator<_Iterator>& __x, const reverse_iterator<_Iterator>& __y) { return !(__x < __y); } - template<typename _Iterator> - inline typename reverse_iterator<_Iterator>::difference_type - operator-(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return __y.base() - __x.base(); } - - template<typename _Iterator> - inline reverse_iterator<_Iterator> - operator+(typename reverse_iterator<_Iterator>::difference_type __n, - const reverse_iterator<_Iterator>& __x) - { return reverse_iterator<_Iterator>(__x.base() - __n); } - // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 280. Comparison of reverse_iterator to const reverse_iterator. template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator==(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return __x.base() == __y.base(); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return __y.base() < __x.base(); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator!=(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return !(__x == __y); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return __y < __x; } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<=(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return !(__y < __x); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>=(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) { return !(__x < __y); } + //@} + +#if __cplusplus < 201103L + template<typename _Iterator> + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } template<typename _IteratorL, typename _IteratorR> -#if __cplusplus >= 201103L - // DR 685. - inline auto + inline typename reverse_iterator<_IteratorL>::difference_type operator-(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) - -> decltype(__y.base() - __x.base()) + { return __y.base() - __x.base(); } #else - inline typename reverse_iterator<_IteratorL>::difference_type + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 685. reverse_iterator/move_iterator difference has invalid signatures + template<typename _IteratorL, typename _IteratorR> + inline _GLIBCXX17_CONSTEXPR auto operator-(const reverse_iterator<_IteratorL>& __x, const reverse_iterator<_IteratorR>& __y) -#endif + -> decltype(__y.base() - __x.base()) { return __y.base() - __x.base(); } - //@} +#endif + + template<typename _Iterator> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } #if __cplusplus >= 201103L // Same as C++14 make_reverse_iterator but used in C++03 mode too. template<typename _Iterator> - inline reverse_iterator<_Iterator> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> __make_reverse_iterator(_Iterator __i) { return reverse_iterator<_Iterator>(__i); } @@ -402,7 +412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 2285. make_reverse_iterator /// Generator function for reverse_iterator. template<typename _Iterator> - inline reverse_iterator<_Iterator> + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> make_reverse_iterator(_Iterator __i) { return reverse_iterator<_Iterator>(__i); } # endif @@ -1018,37 +1028,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename remove_reference<__base_ref>::type&&, __base_ref>::type reference; + _GLIBCXX17_CONSTEXPR move_iterator() : _M_current() { } - explicit + explicit _GLIBCXX17_CONSTEXPR move_iterator(iterator_type __i) : _M_current(__i) { } template<typename _Iter> + _GLIBCXX17_CONSTEXPR move_iterator(const move_iterator<_Iter>& __i) : _M_current(__i.base()) { } - iterator_type + _GLIBCXX17_CONSTEXPR iterator_type base() const { return _M_current; } - reference + _GLIBCXX17_CONSTEXPR reference operator*() const { return static_cast<reference>(*_M_current); } - pointer + _GLIBCXX17_CONSTEXPR pointer operator->() const { return _M_current; } - move_iterator& + _GLIBCXX17_CONSTEXPR move_iterator& operator++() { ++_M_current; return *this; } - move_iterator + _GLIBCXX17_CONSTEXPR move_iterator operator++(int) { move_iterator __tmp = *this; @@ -1056,14 +1068,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __tmp; } - move_iterator& + _GLIBCXX17_CONSTEXPR move_iterator& operator--() { --_M_current; return *this; } - move_iterator + _GLIBCXX17_CONSTEXPR move_iterator operator--(int) { move_iterator __tmp = *this; @@ -1071,29 +1083,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __tmp; } - move_iterator + _GLIBCXX17_CONSTEXPR move_iterator operator+(difference_type __n) const { return move_iterator(_M_current + __n); } - move_iterator& + _GLIBCXX17_CONSTEXPR move_iterator& operator+=(difference_type __n) { _M_current += __n; return *this; } - move_iterator + _GLIBCXX17_CONSTEXPR move_iterator operator-(difference_type __n) const { return move_iterator(_M_current - __n); } - move_iterator& + _GLIBCXX17_CONSTEXPR move_iterator& operator-=(difference_type __n) { _M_current -= __n; return *this; } - reference + _GLIBCXX17_CONSTEXPR reference operator[](difference_type __n) const { return std::move(_M_current[__n]); } }; @@ -1102,100 +1114,93 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // why there are always 2 versions for most of the move_iterator // operators. template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator==(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return __x.base() == __y.base(); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator==(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return __x.base() == __y.base(); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator!=(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return !(__x == __y); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator!=(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return !(__x == __y); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return __x.base() < __y.base(); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return __x.base() < __y.base(); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<=(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return !(__y < __x); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator<=(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return !(__y < __x); } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return __y < __x; } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return __y < __x; } template<typename _IteratorL, typename _IteratorR> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>=(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) { return !(__x < __y); } template<typename _Iterator> - inline bool + inline _GLIBCXX17_CONSTEXPR bool operator>=(const move_iterator<_Iterator>& __x, const move_iterator<_Iterator>& __y) { return !(__x < __y); } // DR 685. template<typename _IteratorL, typename _IteratorR> - inline auto + inline _GLIBCXX17_CONSTEXPR auto operator-(const move_iterator<_IteratorL>& __x, const move_iterator<_IteratorR>& __y) -> decltype(__x.base() - __y.base()) { return __x.base() - __y.base(); } template<typename _Iterator> - inline auto - operator-(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - -> decltype(__x.base() - __y.base()) - { return __x.base() - __y.base(); } - - template<typename _Iterator> - inline move_iterator<_Iterator> + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> operator+(typename move_iterator<_Iterator>::difference_type __n, const move_iterator<_Iterator>& __x) { return __x + __n; } template<typename _Iterator> - inline move_iterator<_Iterator> + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> make_move_iterator(_Iterator __i) { return move_iterator<_Iterator>(__i); } @@ -1203,7 +1208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = typename conditional<__move_if_noexcept_cond <typename iterator_traits<_Iterator>::value_type>::value, _Iterator, move_iterator<_Iterator>>::type> - inline _ReturnType + inline _GLIBCXX17_CONSTEXPR _ReturnType __make_move_if_noexcept_iterator(_Iterator __i) { return _ReturnType(__i); } @@ -1212,7 +1217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _ReturnType = typename conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp*, move_iterator<_Tp*>>::type> - inline _ReturnType + inline _GLIBCXX17_CONSTEXPR _ReturnType __make_move_if_noexcept_iterator(_Tp* __i) { return _ReturnType(__i); } diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h index a8b156d1ec..ce6c3d20e0 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h @@ -1,6 +1,6 @@ // Functions used by iterators -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -75,7 +75,8 @@ _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator> - inline typename iterator_traits<_InputIterator>::difference_type + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type __distance(_InputIterator __first, _InputIterator __last, input_iterator_tag) { @@ -92,7 +93,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _RandomAccessIterator> - inline typename iterator_traits<_RandomAccessIterator>::difference_type + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_RandomAccessIterator>::difference_type __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) { @@ -131,7 +133,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * and are constant time. For other %iterator classes they are linear time. */ template<typename _InputIterator> - inline typename iterator_traits<_InputIterator>::difference_type + inline _GLIBCXX17_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type distance(_InputIterator __first, _InputIterator __last) { // concept requirements -- taken care of in __distance @@ -140,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _InputIterator, typename _Distance> - inline void + inline _GLIBCXX14_CONSTEXPR void __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) { // concept requirements @@ -151,7 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _BidirectionalIterator, typename _Distance> - inline void + inline _GLIBCXX14_CONSTEXPR void __advance(_BidirectionalIterator& __i, _Distance __n, bidirectional_iterator_tag) { @@ -167,7 +170,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _RandomAccessIterator, typename _Distance> - inline void + inline _GLIBCXX14_CONSTEXPR void __advance(_RandomAccessIterator& __i, _Distance __n, random_access_iterator_tag) { @@ -190,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * and are constant time. For other %iterator classes they are linear time. */ template<typename _InputIterator, typename _Distance> - inline void + inline _GLIBCXX17_CONSTEXPR void advance(_InputIterator& __i, _Distance __n) { // concept requirements -- taken care of in __advance @@ -201,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _ForwardIterator> - inline _ForwardIterator + inline _GLIBCXX17_CONSTEXPR _ForwardIterator next(_ForwardIterator __x, typename iterator_traits<_ForwardIterator>::difference_type __n = 1) { @@ -213,7 +216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _BidirectionalIterator> - inline _BidirectionalIterator + inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator prev(_BidirectionalIterator __x, typename iterator_traits<_BidirectionalIterator>::difference_type __n = 1) { diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index 380fbdda9e..24ed016b91 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -1,6 +1,6 @@ // Types used in iterator implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 1f875177a7..0420dbfbba 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -1,6 +1,6 @@ // List implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -76,7 +76,7 @@ namespace std _GLIBCXX_VISIBILITY(default) // "needless" static_cast'ing later on, but it's all safe // downcasting. - /// Common part of a node in the %list. + /// Common part of a node in the %list. struct _List_node_base { _List_node_base* _M_next; @@ -127,14 +127,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp> struct _List_iterator { - typedef _List_iterator<_Tp> _Self; - typedef _List_node<_Tp> _Node; + typedef _List_iterator<_Tp> _Self; + typedef _List_node<_Tp> _Node; - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - typedef _Tp value_type; - typedef _Tp* pointer; - typedef _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; _List_iterator() _GLIBCXX_NOEXCEPT : _M_node() { } @@ -206,15 +206,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp> struct _List_const_iterator { - typedef _List_const_iterator<_Tp> _Self; - typedef const _List_node<_Tp> _Node; - typedef _List_iterator<_Tp> iterator; + typedef _List_const_iterator<_Tp> _Self; + typedef const _List_node<_Tp> _Node; + typedef _List_iterator<_Tp> iterator; - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - typedef _Tp value_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; _List_const_iterator() _GLIBCXX_NOEXCEPT : _M_node() { } @@ -291,7 +291,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Val> inline bool operator!=(const _List_iterator<_Val>& __x, - const _List_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT + const _List_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT { return __x._M_node != __y._M_node; } _GLIBCXX_BEGIN_NAMESPACE_CXX11 @@ -447,8 +447,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_init() _GLIBCXX_NOEXCEPT { - this->_M_impl._M_node._M_next = &this->_M_impl._M_node; - this->_M_impl._M_node._M_prev = &this->_M_impl._M_node; + this->_M_impl._M_node._M_next = &this->_M_impl._M_node; + this->_M_impl._M_node._M_prev = &this->_M_impl._M_node; _M_set_size(0); } }; @@ -497,35 +497,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * pointing to @e D, not to @e A! To get to the head of the %list, * we start at the tail and move forward by one. When this member * iterator's next/previous pointers refer to itself, the %list is - * %empty. + * %empty. */ template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class list : protected _List_base<_Tp, _Alloc> { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif - typedef _List_base<_Tp, _Alloc> _Base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits; - typedef typename _Base::_Node_alloc_type _Node_alloc_type; - typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + typedef _List_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; public: - typedef _Tp value_type; + typedef _Tp value_type; typedef typename _Tp_alloc_traits::pointer pointer; typedef typename _Tp_alloc_traits::const_pointer const_pointer; typedef typename _Tp_alloc_traits::reference reference; typedef typename _Tp_alloc_traits::const_reference const_reference; typedef _List_iterator<_Tp> iterator; typedef _List_const_iterator<_Tp> const_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; protected: // Note that pointers-to-_Node's can be ctor-converted to @@ -562,8 +566,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #else template<typename... _Args> - _Node* - _M_create_node(_Args&&... __args) + _Node* + _M_create_node(_Args&&... __args) { auto __p = this->_M_get_node(); auto& __alloc = _M_get_Node_allocator(); @@ -643,7 +647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __x A %list of identical element and allocator types. * * The newly-created %list uses a copy of the allocation object used - * by @a __x. + * by @a __x (unless the allocator traits dictate a different object). */ list(const list& __x) : _Base(_Node_alloc_traits:: @@ -670,7 +674,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * initializer_list @a __l. This is linear in __l.size(). */ list(initializer_list<value_type> __l, - const allocator_type& __a = allocator_type()) + const allocator_type& __a = allocator_type()) : _Base(_Node_alloc_type(__a)) { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } @@ -702,22 +706,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - list(_InputIterator __first, _InputIterator __last, + list(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(_Node_alloc_type(__a)) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { _M_initialize_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - list(_InputIterator __first, _InputIterator __last, + list(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(_Node_alloc_type(__a)) - { + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_initialize_dispatch(__first, __last, _Integral()); } #endif +#if __cplusplus >= 201103L /** * No explicit dtor needed as the _Base dtor takes care of * things. The _Base dtor only erases the elements, and note @@ -725,13 +730,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * memory is not touched in any way. Managing the pointer is * the user's responsibility. */ + ~list() = default; +#endif /** * @brief %List assignment operator. * @param __x A %list of identical element and allocator types. * - * All the elements of @a __x are copied, but unlike the copy - * constructor, the allocator object is not copied. + * All the elements of @a __x are copied. + * + * Whether the allocator is copied depends on the allocator traits. */ list& operator=(const list& __x); @@ -742,16 +750,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __x A %list of identical element and allocator types. * * The contents of @a __x are moved into this %list (without copying). - * @a __x is a valid, but unspecified %list + * + * Afterwards @a __x is a valid, but unspecified %list + * + * Whether the allocator is moved depends on the allocator traits. */ list& operator=(list&& __x) noexcept(_Node_alloc_traits::_S_nothrow_move()) { constexpr bool __move_storage = - _Node_alloc_traits::_S_propagate_on_move_assign() - || _Node_alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); return *this; } @@ -778,7 +789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This function fills a %list with @a __n copies of the given * value. Note that the assignment completely changes the %list * and that the resulting %list's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ void assign(size_type __n, const value_type& __val) @@ -794,19 +805,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note that the assignment completely changes the %list and * that the resulting %list's size is the same as the number of - * elements assigned. Old data may be lost. + * elements assigned. */ #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - void - assign(_InputIterator __first, _InputIterator __last) - { + void + assign(_InputIterator __first, _InputIterator __last) + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_assign_dispatch(__first, __last, _Integral()); @@ -823,7 +834,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ void assign(initializer_list<value_type> __l) - { this->assign(__l.begin(), __l.end()); } + { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); } #endif /// Get a copy of the memory allocation object. @@ -1023,7 +1034,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ reference back() _GLIBCXX_NOEXCEPT - { + { iterator __tmp = end(); --__tmp; return *__tmp; @@ -1035,7 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ const_reference back() const _GLIBCXX_NOEXCEPT - { + { const_iterator __tmp = end(); --__tmp; return *__tmp; @@ -1062,9 +1073,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { this->_M_insert(begin(), std::move(__x)); } template<typename... _Args> - void - emplace_front(_Args&&... __args) - { this->_M_insert(begin(), std::forward<_Args>(__args)...); } +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args) + { + this->_M_insert(begin(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } #endif /** @@ -1103,9 +1123,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { this->_M_insert(end(), std::move(__x)); } template<typename... _Args> - void - emplace_back(_Args&&... __args) - { this->_M_insert(end(), std::forward<_Args>(__args)...); } +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args) + { + this->_M_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } #endif /** @@ -1137,8 +1166,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * and references. */ template<typename... _Args> - iterator - emplace(const_iterator __position, _Args&&... __args); + iterator + emplace(const_iterator __position, _Args&&... __args); /** * @brief Inserts given value into %list before specified iterator. @@ -1180,7 +1209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * the specified location. Due to the nature of a %list this * operation can be done in constant time, and does not * invalidate iterators and references. - */ + */ iterator insert(const_iterator __position, value_type&& __x) { return emplace(__position, std::move(__x)); } @@ -1279,10 +1308,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * does not invalidate iterators and references. */ template<typename _InputIterator> - void - insert(iterator __position, _InputIterator __first, + void + insert(iterator __position, _InputIterator __first, _InputIterator __last) - { + { list __tmp(__first, __last, get_allocator()); splice(__position, __tmp); } @@ -1348,19 +1377,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * time. Note that the global std::swap() function is * specialized such that std::swap(l1,l2) will feed to this * function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(list& __x) _GLIBCXX_NOEXCEPT { __detail::_List_node_base::swap(this->_M_impl._M_node, - __x._M_impl._M_node); + __x._M_impl._M_node); size_t __xsize = __x._M_get_size(); __x._M_set_size(this->_M_get_size()); this->_M_set_size(__xsize); _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), - __x._M_get_Node_allocator()); + __x._M_get_Node_allocator()); } /** @@ -1372,8 +1403,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void clear() _GLIBCXX_NOEXCEPT { - _Base::_M_clear(); - _Base::_M_init(); + _Base::_M_clear(); + _Base::_M_init(); } // [23.2.2.4] list operations @@ -1567,8 +1598,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * responsibility. */ template<typename _Predicate> - void - remove_if(_Predicate); + void + remove_if(_Predicate); /** * @brief Remove consecutive duplicate elements. @@ -1596,8 +1627,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Managing the pointer is the user's responsibility. */ template<typename _BinaryPredicate> - void - unique(_BinaryPredicate); + void + unique(_BinaryPredicate); /** * @brief Merge sorted lists. @@ -1635,17 +1666,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ #if __cplusplus >= 201103L template<typename _StrictWeakOrdering> - void - merge(list&& __x, _StrictWeakOrdering __comp); + void + merge(list&& __x, _StrictWeakOrdering __comp); template<typename _StrictWeakOrdering> - void - merge(list& __x, _StrictWeakOrdering __comp) - { merge(std::move(__x), __comp); } + void + merge(list& __x, _StrictWeakOrdering __comp) + { merge(std::move(__x), __comp); } #else template<typename _StrictWeakOrdering> - void - merge(list& __x, _StrictWeakOrdering __comp); + void + merge(list& __x, _StrictWeakOrdering __comp); #endif /** @@ -1673,8 +1704,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * elements remain in list order. */ template<typename _StrictWeakOrdering> - void - sort(_StrictWeakOrdering); + void + sort(_StrictWeakOrdering); protected: // Internal constructor functions follow. @@ -1684,16 +1715,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) - { _M_fill_initialize(static_cast<size_type>(__n), __x); } + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_fill_initialize(static_cast<size_type>(__n), __x); } // Called by the range constructor to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) - { + { for (; __first != __last; ++__first) #if __cplusplus >= 201103L emplace_back(*__first); @@ -1732,14 +1763,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } // Called by the range assign to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type); // Called by assign(n,t), and the range assign when it turns out @@ -1758,8 +1789,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_insert(iterator __position, const value_type& __x) { - _Node* __tmp = _M_create_node(__x); - __tmp->_M_hook(__position._M_node); + _Node* __tmp = _M_create_node(__x); + __tmp->_M_hook(__position._M_node); this->_M_inc_size(1); } #else @@ -1778,15 +1809,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _M_erase(iterator __position) _GLIBCXX_NOEXCEPT { this->_M_dec_size(1); - __position._M_node->_M_unhook(); - _Node* __n = static_cast<_Node*>(__position._M_node); + __position._M_node->_M_unhook(); + _Node* __n = static_cast<_Node*>(__position._M_node); #if __cplusplus >= 201103L _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr()); #else _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr()); #endif - _M_put_node(__n); + _M_put_node(__n); } // To implement the splice (and merge) bits of N1599. @@ -1818,16 +1849,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 this->_M_set_size(__x._M_get_size()); __x._M_init(); } - std::__alloc_on_move(this->_M_get_Node_allocator(), - __x._M_get_Node_allocator()); + std::__alloc_on_move(this->_M_get_Node_allocator(), + __x._M_get_Node_allocator()); } void _M_move_assign(list&& __x, false_type) { if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) - _M_move_assign(std::move(__x), true_type{}); - else + _M_move_assign(std::move(__x), true_type{}); + else // The rvalue's allocator cannot be moved, or is not equal, // so we need to individually move each element. _M_assign_dispatch(std::__make_move_if_noexcept_iterator(__x.begin()), diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index b259509206..30339536f5 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -1,6 +1,6 @@ // Map implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -67,6 +67,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER + template <typename _Key, typename _Tp, typename _Compare, typename _Alloc> + class multimap; + /** * @brief A standard container made up of (key,value) pairs, which can be * retrieved based on a key, in logarithmic time. @@ -76,7 +79,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to + * @tparam _Alloc Allocator type, defaults to * allocator<pair<const _Key, _Tp>. * * Meets the requirements of a <a href="tables.html#65">container</a>, a @@ -92,23 +95,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * called (*_unique versus *_equal, same as the standard). */ template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>, - typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > + typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > class map { public: - typedef _Key key_type; - typedef _Tp mapped_type; - typedef std::pair<const _Key, _Tp> value_type; - typedef _Compare key_compare; - typedef _Alloc allocator_type; + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; private: +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif __glibcxx_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept) __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif public: class value_compare @@ -127,7 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER }; private: - /// This turns a red-black tree into a [multi]map. + /// This turns a red-black tree into a [multi]map. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<value_type>::other _Pair_alloc_type; @@ -142,28 +149,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER public: // many of these are specified differently in ISO, but the following are // "functionally equivalent" - 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 typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::reverse_iterator reverse_iterator; + 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 typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + // [23.3.1.1] construct/copy/destroy // (get_allocator() is also listed in this section) /** * @brief Default constructor creates no elements. */ - map() -#if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<allocator_type>::value) +#if __cplusplus < 201103L + map() : _M_t() { } +#else + map() = default; #endif - : _M_t() { } /** * @brief Creates a %map with no elements. @@ -177,25 +189,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief %Map copy constructor. - * @param __x A %map of identical element and allocator types. * - * The newly-created %map uses a copy of the allocation object - * used by @a __x. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L map(const map& __x) : _M_t(__x._M_t) { } +#else + map(const map&) = default; -#if __cplusplus >= 201103L /** * @brief %Map move constructor. - * @param __x A %map of identical element and allocator types. * - * The newly-created %map contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %map. + * The newly-created %map contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %map. */ - map(map&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _M_t(std::move(__x._M_t)) { } + map(map&&) = default; /** * @brief Builds a %map from an initializer_list. @@ -236,10 +245,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Allocator-extended range constructor. template<typename _InputIterator> - map(_InputIterator __first, _InputIterator __last, + map(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _M_t(_Compare(), _Pair_alloc_type(__a)) - { _M_t._M_insert_unique(__first, __last); } + { _M_t._M_insert_unique(__first, __last); } #endif /** @@ -253,9 +262,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * distance(__first,__last)). */ template<typename _InputIterator> - map(_InputIterator __first, _InputIterator __last) + map(_InputIterator __first, _InputIterator __last) : _M_t() - { _M_t._M_insert_unique(__first, __last); } + { _M_t._M_insert_unique(__first, __last); } /** * @brief Builds a %map from a range. @@ -270,36 +279,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * distance(__first,__last)). */ template<typename _InputIterator> - map(_InputIterator __first, _InputIterator __last, + map(_InputIterator __first, _InputIterator __last, const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_unique(__first, __last); } + { _M_t._M_insert_unique(__first, __last); } - // FIXME There is no dtor declared, but we should have something - // generated by Doxygen. I don't know what tags to add to this - // paragraph to make that happen: +#if __cplusplus >= 201103L /** * The dtor only erases the elements, and note that if the elements * themselves are pointers, the pointed-to memory is not touched in any * way. Managing the pointer is the user's responsibility. */ + ~map() = default; +#endif /** * @brief %Map assignment operator. - * @param __x A %map of identical element and allocator types. * - * All the elements of @a __x are copied, but unlike the copy - * constructor, the allocator object is not copied. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L map& operator=(const map& __x) { _M_t = __x._M_t; return *this; } +#else + map& + operator=(const map&) = default; -#if __cplusplus >= 201103L /// Move assignment operator. map& operator=(map&&) = default; @@ -313,7 +323,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %map and * that the resulting %map's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ map& operator=(initializer_list<value_type> __l) @@ -484,7 +494,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::tuple<const key_type&>(__k), std::tuple<>()); #else - __i = insert(__i, value_type(__k, mapped_type())); + __i = insert(__i, value_type(__k, mapped_type())); #endif return (*__i).second; } @@ -593,13 +603,67 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif #if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template<typename, typename> + friend class _Rb_tree_merge_helper; + + template<typename _C2> + void + merge(map<_Key, _Tp, _C2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<map, _C2>; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _C2> + void + merge(map<_Key, _Tp, _C2, _Alloc>&& __source) + { merge(__source); } + + template<typename _C2> + void + merge(multimap<_Key, _Tp, _C2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<map, _C2>; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _C2> + void + merge(multimap<_Key, _Tp, _C2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus > 201402L #define __cpp_lib_map_try_emplace 201411 /** * @brief Attempts to build and insert a std::pair into the %map. * * @param __k Key to use for finding a possibly existing pair in * the map. - * @param __args Arguments used to generate the .second for a new pair + * @param __args Arguments used to generate the .second for a new pair * instance. * * @return A pair, of which the first element is an iterator that points @@ -615,37 +679,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Insertion requires logarithmic time. */ template <typename... _Args> - pair<iterator, bool> - try_emplace(const key_type& __k, _Args&&... __args) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return {__i, true}; - } - return {__i, false}; - } + pair<iterator, bool> + try_emplace(const key_type& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } // move-capable overload template <typename... _Args> - pair<iterator, bool> - try_emplace(key_type&& __k, _Args&&... __args) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return {__i, true}; - } - return {__i, false}; - } + pair<iterator, bool> + try_emplace(key_type&& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } /** * @brief Attempts to build and insert a std::pair into the %map. @@ -654,14 +718,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * pair should be inserted. * @param __k Key to use for finding a possibly existing pair in * the map. - * @param __args Arguments used to generate the .second for a new pair + * @param __args Arguments used to generate the .second for a new pair * instance. * @return An iterator that points to the element with key of the * std::pair built from @a __args (may or may not be that * std::pair). * * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument + * and thus does not return a boolean like the single-argument * try_emplace() does. However, if insertion did not take place, * this function has no effect. * Note that the first parameter is only a hint and can potentially @@ -675,40 +739,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Insertion requires logarithmic time (if the hint is not taken). */ template <typename... _Args> - iterator - try_emplace(const_iterator __hint, const key_type& __k, - _Args&&... __args) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - __i = emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - else - __i = iterator(__true_hint.first); - return __i; - } + iterator + try_emplace(const_iterator __hint, const key_type& __k, + _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } // move-capable overload template <typename... _Args> - iterator - try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - __i = emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - else - __i = iterator(__true_hint.first); - return __i; - } + iterator + try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } #endif /** @@ -717,8 +781,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __x Pair to be inserted (see std::make_pair for easy * creation of pairs). * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is * a bool that is true if the pair was actually inserted. * * This function attempts to insert a (key, value) %pair into the %map. @@ -735,9 +799,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> - std::pair<iterator, bool> - insert(_Pair&& __x) - { return _M_t._M_insert_unique(std::forward<_Pair>(__x)); } + std::pair<iterator, bool> + insert(_Pair&& __x) + { return _M_t._M_insert_unique(std::forward<_Pair>(__x)); } #endif #if __cplusplus >= 201103L @@ -788,9 +852,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> - iterator - insert(const_iterator __position, _Pair&& __x) - { return _M_t._M_insert_unique_(__position, + iterator + insert(const_iterator __position, _Pair&& __x) + { return _M_t._M_insert_unique_(__position, std::forward<_Pair>(__x)); } #endif @@ -803,9 +867,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Complexity similar to that of the range constructor. */ template<typename _InputIterator> - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_unique(__first, __last); } + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_unique(__first, __last); } #if __cplusplus > 201402L #define __cpp_lib_map_insertion 201411 @@ -813,11 +877,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Attempts to insert or assign a std::pair into the %map. * @param __k Key to use for finding a possibly existing pair in * the map. - * @param __obj Argument used to generate the .second for a pair + * @param __obj Argument used to generate the .second for a pair * instance. * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is * a bool that is true if the pair was actually inserted. * * This function attempts to insert a (key, value) %pair into the %map. @@ -829,39 +893,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Insertion requires logarithmic time. */ template <typename _Obj> - pair<iterator, bool> - insert_or_assign(const key_type& __k, _Obj&& __obj) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } + pair<iterator, bool> + insert_or_assign(const key_type& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } // move-capable overload template <typename _Obj> - pair<iterator, bool> - insert_or_assign(key_type&& __k, _Obj&& __obj) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } + pair<iterator, bool> + insert_or_assign(key_type&& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } /** * @brief Attempts to insert or assign a std::pair into the %map. @@ -869,7 +933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * pair should be inserted. * @param __k Key to use for finding a possibly existing pair in * the map. - * @param __obj Argument used to generate the .second for a pair + * @param __obj Argument used to generate the .second for a pair * instance. * * @return An iterator that points to the element with key of @@ -884,44 +948,44 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Insertion requires logarithmic time. */ template <typename _Obj> - iterator - insert_or_assign(const_iterator __hint, - const key_type& __k, _Obj&& __obj) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - { - return emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - __i = iterator(__true_hint.first); - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } + iterator + insert_or_assign(const_iterator __hint, + const key_type& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } // move-capable overload template <typename _Obj> - iterator - insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - { - return emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - __i = iterator(__true_hint.first); - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } + iterator + insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } #endif #if __cplusplus >= 201103L @@ -931,7 +995,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Erases an element from a %map. * @param __position An iterator pointing to the element to be erased. * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such + * @a position prior to the element being erased. If no such * element exists, end() is returned. * * This function erases an element, pointed to by the given @@ -939,6 +1003,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * the element, and that if the element is itself a pointer, * the pointed-to memory is not touched in any way. Managing * the pointer is the user's responsibility. + * + * @{ */ iterator erase(const_iterator __position) @@ -949,6 +1015,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator erase(iterator __position) { return _M_t.erase(__position); } + // @} #else /** * @brief Erases an element from a %map. @@ -1027,6 +1094,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * stateless and empty), so it should be quite fast.) Note * that the global std::swap() function is specialized such * that std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(map& __x) @@ -1129,7 +1198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; } + { return _M_t._M_count_tr(__x); } #endif //@} @@ -1153,8 +1222,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -1178,8 +1247,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) const - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -1198,8 +1267,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -1218,8 +1287,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) const - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -1247,8 +1316,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } #endif //@} @@ -1276,19 +1345,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) const - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<const_iterator, const_iterator>( + _M_t._M_equal_range_tr(__x))) + { + return pair<const_iterator, const_iterator>( + _M_t._M_equal_range_tr(__x)); + } #endif //@} template<typename _K1, typename _T1, typename _C1, typename _A1> - friend bool - operator==(const map<_K1, _T1, _C1, _A1>&, + friend bool + operator==(const map<_K1, _T1, _C1, _A1>&, const map<_K1, _T1, _C1, _A1>&); template<typename _K1, typename _T1, typename _C1, typename _A1> - friend bool - operator<(const map<_K1, _T1, _C1, _A1>&, + friend bool + operator<(const map<_K1, _T1, _C1, _A1>&, const map<_K1, _T1, _C1, _A1>&); }; @@ -1305,7 +1378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator==(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } /** @@ -1322,35 +1395,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator<(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t < __y._M_t; } /// Based on operator== template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator!=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x == __y); } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator>(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return __y < __x; } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator<=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__y < __x); } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator>=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) + const map<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x < __y); } /// See std::map::swap(). @@ -1362,6 +1435,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __x.swap(__y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::map access to internals of compatible maps. + template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc, + typename _Cmp2> + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } // namespace std #endif /* _STL_MAP_H */ diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 94ebf6ebc8..7dc22a96a5 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -1,6 +1,6 @@ // Multimap implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER + template <typename _Key, typename _Tp, typename _Compare, typename _Alloc> + class map; + /** * @brief A standard container made up of (key,value) pairs, which can be * retrieved based on a key, in logarithmic time. @@ -74,7 +77,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to + * @tparam _Alloc Allocator type, defaults to * allocator<pair<const _Key, _Tp>. * * Meets the requirements of a <a href="tables.html#65">container</a>, a @@ -95,19 +98,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER class multimap { public: - typedef _Key key_type; - typedef _Tp mapped_type; - typedef std::pair<const _Key, _Tp> value_type; - typedef _Compare key_compare; - typedef _Alloc allocator_type; + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; private: +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif __glibcxx_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept) __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif public: class value_compare @@ -140,28 +147,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER public: // many of these are specified differently in ISO, but the following are // "functionally equivalent" - 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 typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::reverse_iterator reverse_iterator; + 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 typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif + // [23.3.2] construct/copy/destroy // (get_allocator() is also listed in this section) /** * @brief Default constructor creates no elements. */ - multimap() -#if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<allocator_type>::value) +#if __cplusplus < 201103L + multimap() : _M_t() { } +#else + multimap() = default; #endif - : _M_t() { } /** * @brief Creates a %multimap with no elements. @@ -175,25 +186,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief %Multimap copy constructor. - * @param __x A %multimap of identical element and allocator types. * - * The newly-created %multimap uses a copy of the allocation object - * used by @a __x. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L multimap(const multimap& __x) : _M_t(__x._M_t) { } +#else + multimap(const multimap&) = default; -#if __cplusplus >= 201103L /** * @brief %Multimap move constructor. - * @param __x A %multimap of identical element and allocator types. * - * The newly-created %multimap contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %multimap. + * The newly-created %multimap contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multimap. */ - multimap(multimap&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _M_t(std::move(__x._M_t)) { } + multimap(multimap&&) = default; /** * @brief Builds a %multimap from an initializer_list. @@ -233,10 +242,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Allocator-extended range constructor. template<typename _InputIterator> - multimap(_InputIterator __first, _InputIterator __last, + multimap(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _M_t(_Compare(), _Pair_alloc_type(__a)) - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } #endif /** @@ -249,9 +258,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and NlogN otherwise (where N is distance(__first,__last)). */ template<typename _InputIterator> - multimap(_InputIterator __first, _InputIterator __last) + multimap(_InputIterator __first, _InputIterator __last) : _M_t() - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } /** * @brief Builds a %multimap from a range. @@ -265,36 +274,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and NlogN otherwise (where N is distance(__first,__last)). */ template<typename _InputIterator> - multimap(_InputIterator __first, _InputIterator __last, + multimap(_InputIterator __first, _InputIterator __last, const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } - // FIXME There is no dtor declared, but we should have something generated - // by Doxygen. I don't know what tags to add to this paragraph to make - // that happen: +#if __cplusplus >= 201103L /** * The dtor only erases the elements, and note that if the elements * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. + * way. Managing the pointer is the user's responsibility. */ + ~multimap() = default; +#endif /** * @brief %Multimap assignment operator. - * @param __x A %multimap of identical element and allocator types. * - * All the elements of @a __x are copied, but unlike the copy - * constructor, the allocator object is not copied. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L multimap& operator=(const multimap& __x) { _M_t = __x._M_t; return *this; } +#else + multimap& + operator=(const multimap&) = default; -#if __cplusplus >= 201103L /// Move assignment operator. multimap& operator=(multimap&&) = default; @@ -308,7 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %multimap and * that the resulting %multimap's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ multimap& operator=(initializer_list<value_type> __l) @@ -320,7 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Get a copy of the memory allocation object. allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT + get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_t.get_allocator()); } // iterators @@ -524,9 +534,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> - iterator - insert(_Pair&& __x) - { return _M_t._M_insert_equal(std::forward<_Pair>(__x)); } + iterator + insert(_Pair&& __x) + { return _M_t._M_insert_equal(std::forward<_Pair>(__x)); } #endif /** @@ -561,9 +571,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> - iterator - insert(const_iterator __position, _Pair&& __x) - { return _M_t._M_insert_equal_(__position, + iterator + insert(const_iterator __position, _Pair&& __x) + { return _M_t._M_insert_equal_(__position, std::forward<_Pair>(__x)); } #endif @@ -577,9 +587,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Complexity similar to that of the range constructor. */ template<typename _InputIterator> - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_equal(__first, __last); } + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_equal(__first, __last); } #if __cplusplus >= 201103L /** @@ -594,6 +604,60 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { this->insert(__l.begin(), __l.end()); } #endif +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template<typename, typename> + friend class _Rb_tree_merge_helper; + + template<typename _C2> + void + merge(multimap<_Key, _Tp, _C2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<multimap, _C2>; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _C2> + void + merge(multimap<_Key, _Tp, _C2, _Alloc>&& __source) + { merge(__source); } + + template<typename _C2> + void + merge(map<_Key, _Tp, _C2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<multimap, _C2>; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _C2> + void + merge(map<_Key, _Tp, _C2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 130. Associative erase should return an iterator. @@ -601,7 +665,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Erases an element from a %multimap. * @param __position An iterator pointing to the element to be erased. * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such + * @a position prior to the element being erased. If no such * element exists, end() is returned. * * This function erases an element, pointed to by the given iterator, @@ -609,6 +673,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and that if the element is itself a pointer, the pointed-to memory is * not touched in any way. Managing the pointer is the user's * responsibility. + * + * @{ */ iterator erase(const_iterator __position) @@ -619,6 +685,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator erase(iterator __position) { return _M_t.erase(__position); } + // @} #else /** * @brief Erases an element from a %multimap. @@ -701,6 +768,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * should be quite fast.) * Note that the global std::swap() function is specialized such that * std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(multimap& __x) @@ -822,8 +891,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -847,8 +916,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) const - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -867,8 +936,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -887,8 +956,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) const - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -914,8 +983,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } #endif //@} @@ -941,19 +1010,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) const - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<const_iterator, const_iterator>( + _M_t._M_equal_range_tr(__x))) + { + return pair<const_iterator, const_iterator>( + _M_t._M_equal_range_tr(__x)); + } #endif //@} template<typename _K1, typename _T1, typename _C1, typename _A1> - friend bool - operator==(const multimap<_K1, _T1, _C1, _A1>&, + friend bool + operator==(const multimap<_K1, _T1, _C1, _A1>&, const multimap<_K1, _T1, _C1, _A1>&); template<typename _K1, typename _T1, typename _C1, typename _A1> - friend bool - operator<(const multimap<_K1, _T1, _C1, _A1>&, + friend bool + operator<(const multimap<_K1, _T1, _C1, _A1>&, const multimap<_K1, _T1, _C1, _A1>&); }; @@ -970,7 +1043,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator==(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } /** @@ -987,46 +1060,70 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator<(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t < __y._M_t; } /// Based on operator== template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator!=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x == __y); } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return __y < __x; } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator<=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__y < __x); } /// Based on operator< template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator>=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x < __y); } /// See std::multimap::swap(). template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline void swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x, - multimap<_Key, _Tp, _Compare, _Alloc>& __y) + multimap<_Key, _Tp, _Compare, _Alloc>& __y) _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) { __x.swap(__y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::multimap access to internals of compatible maps. + template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc, + typename _Cmp2> + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } // namespace std #endif /* _STL_MULTIMAP_H */ diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index cc13b3cea3..60a3db844c 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -1,6 +1,6 @@ // Multiset implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER + template<typename _Key, typename _Compare, typename _Alloc> + class set; + /** * @brief A standard container made up of elements, which can be retrieved * in logarithmic time. @@ -91,12 +94,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typename _Alloc = std::allocator<_Key> > class multiset { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif __glibcxx_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept) - __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) + __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif public: // typedefs: @@ -119,29 +126,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; public: - 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 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; // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 103. set::iterator is required to be modifiable, // but this allows modification of keys. - typedef typename _Rep_type::const_iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif // allocation/deallocation /** * @brief Default constructor creates no elements. */ - multiset() -#if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<allocator_type>::value) +#if __cplusplus < 201103L + multiset() : _M_t() { } +#else + multiset() = default; #endif - : _M_t() { } /** * @brief Creates a %multiset with no elements. @@ -163,9 +174,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and NlogN otherwise (where N is distance(__first,__last)). */ template<typename _InputIterator> - multiset(_InputIterator __first, _InputIterator __last) + multiset(_InputIterator __first, _InputIterator __last) : _M_t() - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } /** * @brief Builds a %multiset from a range. @@ -179,33 +190,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and NlogN otherwise (where N is distance(__first,__last)). */ template<typename _InputIterator> - multiset(_InputIterator __first, _InputIterator __last, + multiset(_InputIterator __first, _InputIterator __last, const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } /** * @brief %Multiset copy constructor. - * @param __x A %multiset of identical element and allocator types. * - * The newly-created %multiset uses a copy of the allocation object used - * by @a __x. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L multiset(const multiset& __x) : _M_t(__x._M_t) { } +#else + multiset(const multiset&) = default; -#if __cplusplus >= 201103L /** * @brief %Multiset move constructor. - * @param __x A %multiset of identical element and allocator types. * - * The newly-created %multiset contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %multiset. + * The newly-created %multiset contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multiset. */ - multiset(multiset&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _M_t(std::move(__x._M_t)) { } + multiset(multiset&&) = default; /** * @brief Builds a %multiset from an initializer_list. @@ -245,27 +254,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Allocator-extended range constructor. template<typename _InputIterator> - multiset(_InputIterator __first, _InputIterator __last, + multiset(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _M_t(_Compare(), _Key_alloc_type(__a)) - { _M_t._M_insert_equal(__first, __last); } + { _M_t._M_insert_equal(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~multiset() = default; #endif /** * @brief %Multiset assignment operator. - * @param __x A %multiset of identical element and allocator types. * - * All the elements of @a __x are copied, but unlike the copy - * constructor, the allocator object is not copied. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L multiset& operator=(const multiset& __x) { _M_t = __x._M_t; return *this; } +#else + multiset& + operator=(const multiset&) = default; -#if __cplusplus >= 201103L /// Move assignment operator. multiset& operator=(multiset&&) = default; @@ -279,7 +296,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %multiset and * that the resulting %multiset's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ multiset& operator=(initializer_list<value_type> __l) @@ -403,6 +420,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * be quite fast.) * Note that the global std::swap() function is specialized such that * std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(multiset& __x) @@ -518,9 +537,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Complexity similar to that of the range constructor. */ template<typename _InputIterator> - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_equal(__first, __last); } + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_equal(__first, __last); } #if __cplusplus >= 201103L /** @@ -535,6 +554,60 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { this->insert(__l.begin(), __l.end()); } #endif +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template<typename, typename> + friend class _Rb_tree_merge_helper; + + template<typename _Compare1> + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _Compare1> + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template<typename _Compare1> + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _Compare1> + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 130. Associative erase should return an iterator. @@ -542,7 +615,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Erases an element from a %multiset. * @param __position An iterator pointing to the element to be erased. * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such + * @a position prior to the element being erased. If no such * element exists, end() is returned. * * This function erases an element, pointed to by the given iterator, @@ -716,14 +789,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } template<typename _Kt> auto lower_bound(const _Kt& __x) const - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -746,14 +819,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } template<typename _Kt> auto upper_bound(const _Kt& __x) const - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -785,25 +858,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } template<typename _Kt> auto equal_range(const _Kt& __x) const - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } #endif //@} template<typename _K1, typename _C1, typename _A1> - friend bool - operator==(const multiset<_K1, _C1, _A1>&, + friend bool + operator==(const multiset<_K1, _C1, _A1>&, const multiset<_K1, _C1, _A1>&); template<typename _K1, typename _C1, typename _A1> - friend bool - operator< (const multiset<_K1, _C1, _A1>&, + friend bool + operator< (const multiset<_K1, _C1, _A1>&, const multiset<_K1, _C1, _A1>&); }; @@ -878,6 +951,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __x.swap(__y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::multiset access to internals of compatible sets. + template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } // namespace std #endif /* _STL_MULTISET_H */ diff --git a/libstdc++-v3/include/bits/stl_numeric.h b/libstdc++-v3/include/bits/stl_numeric.h index a414b029f5..9f9816428c 100644 --- a/libstdc++-v3/include/bits/stl_numeric.h +++ b/libstdc++-v3/include/bits/stl_numeric.h @@ -1,6 +1,6 @@ // Numeric functions implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 37ee5cc405..b6245b65cd 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -1,6 +1,6 @@ // Pair implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -76,7 +76,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; /// piecewise_construct - constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); + _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = + piecewise_construct_t(); // Forward declarations. template<typename...> @@ -88,52 +89,102 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Concept utility functions, reused in conditionally-explicit // constructors. // See PR 70437, don't look at is_constructible or - // is_convertible if the decayed types are the same to + // is_convertible if the types are the same to // avoid querying those properties for incomplete types. - template <typename _T1, typename _T2, typename _U1, typename _U2> - constexpr bool _ConstructiblePair() - { - return __and_<__or_<is_same<typename decay<_T1>::type, - typename decay<_U1>::type>, - is_constructible<_T1, const _U1&>>, - __or_<is_same<typename decay<_T2>::type, - typename decay<_U2>::type>, - is_constructible<_T2, const _U2&>>>::value; - } - - template <typename _T1, typename _T2, typename _U1, typename _U2> - constexpr bool _ImplicitlyConvertiblePair() - { - return __and_<__or_<is_same<typename decay<_T1>::type, - typename decay<_U1>::type>, - is_convertible<const _U1&, _T1>>, - __or_<is_same<typename decay<_T2>::type, - typename decay<_U2>::type>, - is_convertible<const _U2&, _T2>>>::value; - } - - template <typename _T1, typename _T2, typename _U1, typename _U2> - constexpr bool _MoveConstructiblePair() - { - return __and_<__or_<is_same<typename decay<_T1>::type, - typename decay<_U1>::type>, - is_constructible<_T1, _U1&&>>, - __or_<is_same<typename decay<_T2>::type, - typename decay<_U2>::type>, - is_constructible<_T2, _U2&&>>>::value; - } - - template <typename _T1, typename _T2, typename _U1, typename _U2> - constexpr bool _ImplicitlyMoveConvertiblePair() - { - return __and_<__or_<is_same<typename decay<_T1>::type, - typename decay<_U1>::type>, - is_convertible<_U1&&, _T1>>, - __or_<is_same<typename decay<_T2>::type, - typename decay<_U2>::type>, - is_convertible<_U2&&, _T2>>>::value; - } + template <bool, typename _T1, typename _T2> + struct _PCC + { + template <typename _U1, typename _U2> + static constexpr bool _ConstructiblePair() + { + return __and_<is_constructible<_T1, const _U1&>, + is_constructible<_T2, const _U2&>>::value; + } + + template <typename _U1, typename _U2> + static constexpr bool _ImplicitlyConvertiblePair() + { + return __and_<is_convertible<const _U1&, _T1>, + is_convertible<const _U2&, _T2>>::value; + } + + template <typename _U1, typename _U2> + static constexpr bool _MoveConstructiblePair() + { + return __and_<is_constructible<_T1, _U1&&>, + is_constructible<_T2, _U2&&>>::value; + } + + template <typename _U1, typename _U2> + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return __and_<is_convertible<_U1&&, _T1>, + is_convertible<_U2&&, _T2>>::value; + } + + template <bool __implicit, typename _U1, typename _U2> + static constexpr bool _CopyMovePair() + { + using __do_converts = __and_<is_convertible<const _U1&, _T1>, + is_convertible<_U2&&, _T2>>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_<is_constructible<_T1, const _U1&>, + is_constructible<_T2, _U2&&>, + __converts + >::value; + } + + template <bool __implicit, typename _U1, typename _U2> + static constexpr bool _MoveCopyPair() + { + using __do_converts = __and_<is_convertible<_U1&&, _T1>, + is_convertible<const _U2&, _T2>>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_<is_constructible<_T1, _U1&&>, + is_constructible<_T2, const _U2&&>, + __converts + >::value; + } + }; + + template <typename _T1, typename _T2> + struct _PCC<false, _T1, _T2> + { + template <typename _U1, typename _U2> + static constexpr bool _ConstructiblePair() + { + return false; + } + + template <typename _U1, typename _U2> + static constexpr bool _ImplicitlyConvertiblePair() + { + return false; + } + template <typename _U1, typename _U2> + static constexpr bool _MoveConstructiblePair() + { + return false; + } + + template <typename _U1, typename _U2> + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return false; + } + }; + + // PR libstdc++/79141, a utility type for preventing + // initialization of an argument of a disabled assignment + // operator from a pair of empty braces. + struct __nonesuch_no_braces : std::__nonesuch { + explicit __nonesuch_no_braces(const __nonesuch&) = delete; + }; #endif @@ -186,16 +237,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { } #else + // Shortcut for constraining the templates that don't take pairs. + using _PCCP = _PCC<true, _T1, _T2>; + template<typename _U1 = _T1, typename _U2=_T2, typename - enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>() - && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), + enable_if<_PCCP::template + _ConstructiblePair<_U1, _U2>() + && _PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), bool>::type=true> constexpr pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { } template<typename _U1 = _T1, typename _U2=_T2, typename - enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>() - && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), + enable_if<_PCCP::template + _ConstructiblePair<_U1, _U2>() + && !_PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), bool>::type=false> explicit constexpr pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { } @@ -207,16 +265,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { } #else + // Shortcut for constraining the templates that take pairs. + template <typename _U1, typename _U2> + using _PCCFP = _PCC<!is_same<_T1, _U1>::value + || !is_same<_T2, _U2>::value, + _T1, _T2>; + template<typename _U1, typename _U2, typename - enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>() - && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), - bool>::type=true> + enable_if<_PCCFP<_U1, _U2>::template + _ConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> constexpr pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { } template<typename _U1, typename _U2, typename - enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>() - && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), + enable_if<_PCCFP<_U1, _U2>::template + _ConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), bool>::type=false> explicit constexpr pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { } @@ -226,75 +294,67 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 811. template<typename _U1, typename - enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>() - && _MoveConstructiblePair<_T1, _T2, _U1, _T2>() - && _ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>() - && _ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _T2>(), + enable_if<_PCCP::template + _MoveCopyPair<true, _U1, _T2>(), bool>::type=true> constexpr pair(_U1&& __x, const _T2& __y) : first(std::forward<_U1>(__x)), second(__y) { } template<typename _U1, typename - enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>() - && _MoveConstructiblePair<_T1, _T2, _U1, _T2>() - && (!_ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>() - || !_ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _T2>()), + enable_if<_PCCP::template + _MoveCopyPair<false, _U1, _T2>(), bool>::type=false> explicit constexpr pair(_U1&& __x, const _T2& __y) : first(std::forward<_U1>(__x)), second(__y) { } template<typename _U2, typename - enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>() - && _MoveConstructiblePair<_T1, _T2, _T1, _U2>() - && _ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>() - && _ImplicitlyMoveConvertiblePair<_T1, _T2, - _T1, _U2>(), + enable_if<_PCCP::template + _CopyMovePair<true, _T1, _U2>(), bool>::type=true> constexpr pair(const _T1& __x, _U2&& __y) : first(__x), second(std::forward<_U2>(__y)) { } template<typename _U2, typename - enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>() - && _MoveConstructiblePair<_T1, _T2, _T1, _U2>() - && (!_ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>() - || !_ImplicitlyMoveConvertiblePair<_T1, _T2, - _T1, _U2>()), + enable_if<_PCCP::template + _CopyMovePair<false, _T1, _U2>(), bool>::type=false> explicit pair(const _T1& __x, _U2&& __y) : first(__x), second(std::forward<_U2>(__y)) { } template<typename _U1, typename _U2, typename - enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>() - && _ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _U2>(), + enable_if<_PCCP::template + _MoveConstructiblePair<_U1, _U2>() + && _PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), bool>::type=true> constexpr pair(_U1&& __x, _U2&& __y) : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } template<typename _U1, typename _U2, typename - enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>() - && !_ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _U2>(), + enable_if<_PCCP::template + _MoveConstructiblePair<_U1, _U2>() + && !_PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), bool>::type=false> explicit constexpr pair(_U1&& __x, _U2&& __y) : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } template<typename _U1, typename _U2, typename - enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>() - && _ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _U2>(), + enable_if<_PCCFP<_U1, _U2>::template + _MoveConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), bool>::type=true> constexpr pair(pair<_U1, _U2>&& __p) : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) { } template<typename _U1, typename _U2, typename - enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>() - && !_ImplicitlyMoveConvertiblePair<_T1, _T2, - _U1, _U2>(), + enable_if<_PCCFP<_U1, _U2>::template + _MoveConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), bool>::type=false> explicit constexpr pair(pair<_U1, _U2>&& __p) : first(std::forward<_U1>(__p.first)), @@ -304,7 +364,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); pair& - operator=(const pair& __p) + operator=(typename conditional< + __and_<is_copy_assignable<_T1>, + is_copy_assignable<_T2>>::value, + const pair&, const __nonesuch_no_braces&>::type __p) { first = __p.first; second = __p.second; @@ -312,7 +375,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } pair& - operator=(pair&& __p) + operator=(typename conditional< + __not_<__and_<is_copy_assignable<_T1>, + is_copy_assignable<_T2>>>::value, + const pair&, const __nonesuch_no_braces&>::type __p) = delete; + + pair& + operator=(typename conditional< + __and_<is_move_assignable<_T1>, + is_move_assignable<_T2>>::value, + pair&&, __nonesuch_no_braces&&>::type __p) noexcept(__and_<is_nothrow_move_assignable<_T1>, is_nothrow_move_assignable<_T2>>::value) { @@ -322,7 +394,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - pair& + typename enable_if<__and_<is_assignable<_T1&, const _U1&>, + is_assignable<_T2&, const _U2&>>::value, + pair&>::type operator=(const pair<_U1, _U2>& __p) { first = __p.first; @@ -331,7 +405,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _U1, typename _U2> - pair& + typename enable_if<__and_<is_assignable<_T1&, _U1&&>, + is_assignable<_T2&, _U2&&>>::value, + pair&>::type operator=(pair<_U1, _U2>&& __p) { first = std::forward<_U1>(__p.first); @@ -341,8 +417,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(pair& __p) - noexcept(__is_nothrow_swappable<_T1>::value - && __is_nothrow_swappable<_T2>::value) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) { using std::swap; swap(first, __p.first); @@ -357,6 +433,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif }; +#if __cpp_deduction_guides >= 201606 + template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>; +#endif + /// Two pairs of the same type are equal iff their members are equal. template<typename _T1, typename _T2> inline _GLIBCXX_CONSTEXPR bool @@ -399,11 +479,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Note: no std::swap overloads in C++03 mode, this has performance // implications, see, eg, libstdc++/38466. template<typename _T1, typename _T2> - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_T1>, + __is_swappable<_T2>>::value>::type +#else + void +#endif swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template<typename _T1, typename _T2> + typename enable_if<!__and_<__is_swappable<_T1>, + __is_swappable<_T2>>::value>::type + swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; #endif +#endif // __cplusplus >= 201103L /** * @brief A convenience wrapper for creating a pair from two objects. diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index 9caca03cd0..c49f371fbc 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -1,6 +1,6 @@ // Queue implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -95,20 +95,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Sequence = deque<_Tp> > class queue { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif __glibcxx_class_requires(_Sequence, _FrontInsertionSequenceConcept) __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif template<typename _Tp1, typename _Seq1> - friend bool - operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + friend bool + operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); template<typename _Tp1, typename _Seq1> - friend bool - operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + friend bool + operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); #if __cplusplus >= 201103L template<typename _Alloc> @@ -117,21 +121,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; protected: - /** - * 'c' is the underlying container. Maintainers wondering why - * this isn't uglified as per style guidelines should note that - * this name is specified in the standard, [23.2.3.1]. (Why? - * Presumably for the same reason that it's protected instead + /* Maintainers wondering why this isn't uglified as per style + * guidelines should note that this name is specified in the standard, + * C++98 [23.2.3.1]. + * (Why? Presumably for the same reason that it's protected instead * of private: to allow derivation. But none of the other * containers allow for derivation. Odd.) */ + /// @c c is the underlying container. _Sequence c; public: @@ -143,12 +147,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION queue(const _Sequence& __c = _Sequence()) : c(__c) { } #else + template<typename _Seq = _Sequence, typename _Requires = typename + enable_if<is_default_constructible<_Seq>::value>::type> + queue() + : c() { } + explicit queue(const _Sequence& __c) : c(__c) { } explicit - queue(_Sequence&& __c = _Sequence()) + queue(_Sequence&& __c) : c(std::move(__c)) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> @@ -247,11 +256,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION push(value_type&& __x) { c.push_back(std::move(__x)); } +#if __cplusplus > 201402L template<typename... _Args> - void - emplace(_Args&&... __args) + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template<typename... _Args> + void + emplace(_Args&&... __args) { c.emplace_back(std::forward<_Args>(__args)...); } #endif +#endif /** * @brief Removes first element. @@ -274,12 +290,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(queue& __q) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else noexcept(__is_nothrow_swappable<_Tp>::value) +#endif { using std::swap; swap(c, __q.c); } -#endif +#endif // __cplusplus >= 201103L }; /** @@ -342,7 +362,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Tp, typename _Seq> - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y) noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } @@ -350,7 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Seq, typename _Alloc> struct uses_allocator<queue<_Tp, _Seq>, _Alloc> : public uses_allocator<_Seq, _Alloc>::type { }; -#endif +#endif // __cplusplus >= 201103L /** * @brief A standard container automatically sorting its contents. @@ -359,12 +385,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @tparam _Tp Type of element. * @tparam _Sequence Type of underlying sequence, defaults to vector<_Tp>. - * @tparam _Compare Comparison function object type, defaults to + * @tparam _Compare Comparison function object type, defaults to * less<_Sequence::value_type>. * * This is not a true container, but an @e adaptor. It holds * another container, and provides a wrapper interface to that - * container. The wrapper is what enforces priority-based sorting + * container. The wrapper is what enforces priority-based sorting * and %queue behavior. Very few of the standard container/sequence * interface requirements are met (e.g., iterators). * @@ -396,14 +422,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Compare = less<typename _Sequence::value_type> > class priority_queue { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif __glibcxx_class_requires(_Sequence, _SequenceConcept) __glibcxx_class_requires(_Sequence, _RandomAccessContainerConcept) __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) __glibcxx_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept) +#endif #if __cplusplus >= 201103L template<typename _Alloc> @@ -412,11 +442,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2684. priority_queue lacking comparator typedef + typedef _Compare value_compare; protected: // See queue::c for notes on these names. @@ -434,43 +467,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : c(__s), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } #else + template<typename _Seq = _Sequence, typename _Requires = typename + enable_if<__and_<is_default_constructible<_Compare>, + is_default_constructible<_Seq>>::value>::type> + priority_queue() + : c(), comp() { } + explicit - priority_queue(const _Compare& __x, - const _Sequence& __s) + priority_queue(const _Compare& __x, const _Sequence& __s) : c(__s), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } explicit - priority_queue(const _Compare& __x = _Compare(), - _Sequence&& __s = _Sequence()) + priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()) : c(std::move(__s)), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> explicit priority_queue(const _Alloc& __a) - : c(__a) { } + : c(__a), comp() { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> priority_queue(const _Compare& __x, const _Alloc& __a) - : c(__x, __a) { } + : c(__a), comp(__x) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> priority_queue(const _Compare& __x, const _Sequence& __c, const _Alloc& __a) - : c(__x, __c, __a) { } + : c(__c, __a), comp(__x) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> priority_queue(const _Compare& __x, _Sequence&& __c, const _Alloc& __a) - : c(__x, std::move(__c), __a) { } + : c(std::move(__c), __a), comp(__x) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> priority_queue(const priority_queue& __q, const _Alloc& __a) - : c(__q.c, __a) { } + : c(__q.c, __a), comp(__q.comp) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> priority_queue(priority_queue&& __q, const _Alloc& __a) - : c(std::move(__q.c), __a) { } + : c(std::move(__q.c), __a), comp(std::move(__q.comp)) { } #endif /** @@ -490,33 +527,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ #if __cplusplus < 201103L template<typename _InputIterator> - priority_queue(_InputIterator __first, _InputIterator __last, + priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x = _Compare(), const _Sequence& __s = _Sequence()) : c(__s), comp(__x) - { + { __glibcxx_requires_valid_range(__first, __last); c.insert(c.end(), __first, __last); std::make_heap(c.begin(), c.end(), comp); } #else template<typename _InputIterator> - priority_queue(_InputIterator __first, _InputIterator __last, + priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, const _Sequence& __s) : c(__s), comp(__x) - { + { __glibcxx_requires_valid_range(__first, __last); c.insert(c.end(), __first, __last); std::make_heap(c.begin(), c.end(), comp); } template<typename _InputIterator> - priority_queue(_InputIterator __first, _InputIterator __last, + priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x = _Compare(), _Sequence&& __s = _Sequence()) : c(std::move(__s)), comp(__x) - { + { __glibcxx_requires_valid_range(__first, __last); c.insert(c.end(), __first, __last); std::make_heap(c.begin(), c.end(), comp); @@ -570,8 +607,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename... _Args> - void - emplace(_Args&&... __args) + void + emplace(_Args&&... __args) { c.emplace_back(std::forward<_Args>(__args)...); std::push_heap(c.begin(), c.end(), comp); @@ -600,21 +637,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(priority_queue& __pq) - noexcept(__is_nothrow_swappable<_Tp>::value - && __is_nothrow_swappable<_Compare>::value) + noexcept(__and_< +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + __is_nothrow_swappable<_Sequence>, +#else + __is_nothrow_swappable<_Tp>, +#endif + __is_nothrow_swappable<_Compare> + >::value) { using std::swap; swap(c, __pq.c); swap(comp, __pq.comp); } -#endif +#endif // __cplusplus >= 201103L }; // No equality/comparison operators are provided for priority_queue. #if __cplusplus >= 201103L template<typename _Tp, typename _Sequence, typename _Compare> - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Sequence>, + __is_swappable<_Compare>>::value>::type +#else + void +#endif swap(priority_queue<_Tp, _Sequence, _Compare>& __x, priority_queue<_Tp, _Sequence, _Compare>& __y) noexcept(noexcept(__x.swap(__y))) @@ -624,7 +674,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Alloc> struct uses_allocator<priority_queue<_Tp, _Sequence, _Compare>, _Alloc> : public uses_allocator<_Sequence, _Alloc>::type { }; -#endif +#endif // __cplusplus >= 201103L _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/stl_raw_storage_iter.h b/libstdc++-v3/include/bits/stl_raw_storage_iter.h index 8b5e793dbc..4ad9a91377 100644 --- a/libstdc++-v3/include/bits/stl_raw_storage_iter.h +++ b/libstdc++-v3/include/bits/stl_raw_storage_iter.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -86,17 +86,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - raw_storage_iterator<_OutputIterator, _Tp>& +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2127. Move-construction with raw_storage_iterator + raw_storage_iterator& + operator=(_Tp&& __element) + { + std::_Construct(std::__addressof(*_M_iter), std::move(__element)); + return *this; + } +#endif + + raw_storage_iterator& operator++() { ++_M_iter; return *this; } - raw_storage_iterator<_OutputIterator, _Tp> + raw_storage_iterator operator++(int) { - raw_storage_iterator<_OutputIterator, _Tp> __tmp = *this; + raw_storage_iterator __tmp = *this; ++_M_iter; return __tmp; } diff --git a/libstdc++-v3/include/bits/stl_relops.h b/libstdc++-v3/include/bits/stl_relops.h index 2e19dd1328..a2614bd304 100644 --- a/libstdc++-v3/include/bits/stl_relops.h +++ b/libstdc++-v3/include/bits/stl_relops.h @@ -1,6 +1,6 @@ // std::rel_ops implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index f5e0603d42..817bc2d870 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -1,6 +1,6 @@ // Set implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER + template<typename _Key, typename _Compare, typename _Alloc> + class multiset; + /** * @brief A standard container made up of unique keys, which can be * retrieved in logarithmic time. @@ -89,12 +92,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typename _Alloc = std::allocator<_Key> > class set { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif __glibcxx_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept) __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif public: // typedefs: @@ -120,30 +127,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER public: //@{ /// Iterator-related typedefs. - 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 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; // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 103. set::iterator is required to be modifiable, // but this allows modification of keys. - typedef typename _Rep_type::const_iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; //@} +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + // allocation/deallocation /** * @brief Default constructor creates no elements. */ - set() -#if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<allocator_type>::value) +#if __cplusplus < 201103L + set() : _M_t() { } +#else + set() = default; #endif - : _M_t() { } /** * @brief Creates a %set with no elements. @@ -187,29 +199,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_unique(__first, __last); } + { _M_t._M_insert_unique(__first, __last); } /** * @brief %Set copy constructor. - * @param __x A %set of identical element and allocator types. * - * The newly-created %set uses a copy of the allocation object used - * by @a __x. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L set(const set& __x) : _M_t(__x._M_t) { } +#else + set(const set&) = default; -#if __cplusplus >= 201103L /** * @brief %Set move constructor - * @param __x A %set of identical element and allocator types. * - * The newly-created %set contains the exact contents of @a x. - * The contents of @a x are a valid, but unspecified %set. + * The newly-created %set contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %set. */ - set(set&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _M_t(std::move(__x._M_t)) { } + set(set&&) = default; /** * @brief Builds a %set from an initializer_list. @@ -249,27 +258,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Allocator-extended range constructor. template<typename _InputIterator> - set(_InputIterator __first, _InputIterator __last, + set(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _M_t(_Compare(), _Key_alloc_type(__a)) - { _M_t._M_insert_unique(__first, __last); } + { _M_t._M_insert_unique(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~set() = default; #endif /** * @brief %Set assignment operator. - * @param __x A %set of identical element and allocator types. * - * All the elements of @a __x are copied, but unlike the copy - * constructor, the allocator object is not copied. + * Whether the allocator is copied depends on the allocator traits. */ +#if __cplusplus < 201103L set& operator=(const set& __x) { _M_t = __x._M_t; return *this; } +#else + set& + operator=(const set&) = default; -#if __cplusplus >= 201103L /// Move assignment operator. set& operator=(set&&) = default; @@ -283,7 +300,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %set and * that the resulting %set's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ set& operator=(initializer_list<value_type> __l) @@ -407,6 +424,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * stateless and empty), so it should be quite fast.) Note * that the global std::swap() function is specialized such * that std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(set& __x) @@ -550,6 +569,60 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { this->insert(__l.begin(), __l.end()); } #endif +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template<typename, typename> + friend class _Rb_tree_merge_helper; + + template<typename _Compare1> + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<set, _Compare1>; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _Compare1> + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template<typename _Compare1> + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper<set, _Compare1>; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template<typename _Compare1> + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 130. Associative erase should return an iterator. @@ -670,7 +743,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER auto count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; } + { return _M_t._M_count_tr(__x); } #endif //@} @@ -735,14 +808,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto lower_bound(const _Kt& __x) - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } template<typename _Kt> auto lower_bound(const _Kt& __x) const - -> decltype(_M_t._M_lower_bound_tr(__x)) - { return _M_t._M_lower_bound_tr(__x); } + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } #endif //@} @@ -765,14 +838,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto upper_bound(const _Kt& __x) - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } template<typename _Kt> auto upper_bound(const _Kt& __x) const - -> decltype(_M_t._M_upper_bound_tr(__x)) - { return _M_t._M_upper_bound_tr(__x); } + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } #endif //@} @@ -804,14 +877,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Kt> auto equal_range(const _Kt& __x) - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } template<typename _Kt> auto equal_range(const _Kt& __x) const - -> decltype(_M_t._M_equal_range_tr(__x)) - { return _M_t._M_equal_range_tr(__x); } + -> decltype(pair<iterator, iterator>(_M_t._M_equal_range_tr(__x))) + { return pair<iterator, iterator>(_M_t._M_equal_range_tr(__x)); } #endif //@} @@ -894,5 +967,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __x.swap(__y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::set access to internals of compatible sets. + template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>, _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } //namespace std #endif /* _STL_SET_H */ diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index ea1d149b56..ac59ec715c 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -1,6 +1,6 @@ // Stack implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -98,21 +98,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Sequence = deque<_Tp> > class stack { +#ifdef _GLIBCXX_CONCEPT_CHECKS // concept requirements typedef typename _Sequence::value_type _Sequence_value_type; -#if __cplusplus < 201103L +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) -#endif +# endif __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif template<typename _Tp1, typename _Seq1> - friend bool - operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + friend bool + operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); template<typename _Tp1, typename _Seq1> - friend bool - operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + friend bool + operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); #if __cplusplus >= 201103L template<typename _Alloc> @@ -121,11 +123,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; protected: // See queue::c for notes on this name. @@ -141,12 +143,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION stack(const _Sequence& __c = _Sequence()) : c(__c) { } #else + template<typename _Seq = _Sequence, typename _Requires = typename + enable_if<is_default_constructible<_Seq>::value>::type> + stack() + : c() { } + explicit stack(const _Sequence& __c) : c(__c) { } explicit - stack(_Sequence&& __c = _Sequence()) + stack(_Sequence&& __c) : c(std::move(__c)) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> @@ -223,11 +230,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION push(value_type&& __x) { c.push_back(std::move(__x)); } +#if __cplusplus > 201402L template<typename... _Args> - void - emplace(_Args&&... __args) + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template<typename... _Args> + void + emplace(_Args&&... __args) { c.emplace_back(std::forward<_Args>(__args)...); } #endif +#endif /** * @brief Removes first element. @@ -250,12 +264,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L void swap(stack& __s) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else noexcept(__is_nothrow_swappable<_Tp>::value) +#endif { using std::swap; swap(c, __s.c); } -#endif +#endif // __cplusplus >= 201103L }; /** @@ -319,7 +337,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Tp, typename _Seq> - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y) noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } @@ -327,7 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Seq, typename _Alloc> struct uses_allocator<stack<_Tp, _Seq>, _Alloc> : public uses_allocator<_Seq, _Alloc>::type { }; -#endif +#endif // __cplusplus >= 201103L _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h index 0dc2b70345..03b4cd29ff 100644 --- a/libstdc++-v3/include/bits/stl_tempbuf.h +++ b/libstdc++-v3/include/bits/stl_tempbuf.h @@ -1,6 +1,6 @@ // Temporary buffer implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 8697a711a5..ce7ecdaa87 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1,6 +1,6 @@ // RB tree implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -66,7 +66,10 @@ #include <bits/cpp_type_traits.h> #include <ext/alloc_traits.h> #if __cplusplus >= 201103L -#include <ext/aligned_buffer.h> +# include <ext/aligned_buffer.h> +#endif +#if __cplusplus > 201402L +# include <bits/node_handle.h> #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -134,6 +137,81 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + // Helper type offering value initialization guarantee on the compare functor. + template<typename _Key_compare> + struct _Rb_tree_key_compare + { + _Key_compare _M_key_compare; + + _Rb_tree_key_compare() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Key_compare>::value) + : _M_key_compare() + { } + + _Rb_tree_key_compare(const _Key_compare& __comp) + : _M_key_compare(__comp) + { } + +#if __cplusplus >= 201103L + // Copy constructor added for consistency with C++98 mode. + _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default; + + _Rb_tree_key_compare(_Rb_tree_key_compare&& __x) + noexcept(is_nothrow_copy_constructible<_Key_compare>::value) + : _M_key_compare(__x._M_key_compare) + { } +#endif + }; + + // Helper type to manage default initialization of node count and header. + struct _Rb_tree_header + { + _Rb_tree_node_base _M_header; + size_t _M_node_count; // Keeps track of size of tree. + + _Rb_tree_header() _GLIBCXX_NOEXCEPT + { + _M_header._M_color = _S_red; + _M_reset(); + } + +#if __cplusplus >= 201103L + _Rb_tree_header(_Rb_tree_header&& __x) noexcept + { + if (__x._M_header._M_parent != nullptr) + _M_move_data(__x); + else + { + _M_header._M_color = _S_red; + _M_reset(); + } + } +#endif + + void + _M_move_data(_Rb_tree_header& __from) + { + _M_header._M_color = __from._M_header._M_color; + _M_header._M_parent = __from._M_header._M_parent; + _M_header._M_left = __from._M_header._M_left; + _M_header._M_right = __from._M_header._M_right; + _M_header._M_parent->_M_parent = &_M_header; + _M_node_count = __from._M_node_count; + + __from._M_reset(); + } + + void + _M_reset() + { + _M_header._M_parent = 0; + _M_header._M_left = &_M_header; + _M_header._M_right = &_M_header; + _M_node_count = 0; + } + }; + template<typename _Val> struct _Rb_tree_node : public _Rb_tree_node_base { @@ -356,6 +434,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef void type; }; #endif +#if __cplusplus > 201402L + template<typename _Tree1, typename _Cmp2> + struct _Rb_tree_merge_helper { }; +#endif + template<typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, typename _Alloc = allocator<_Val> > class _Rb_tree @@ -591,47 +674,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Unused _Is_pod_comparator is kept as it is part of mangled name. template<typename _Key_compare, bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)> - struct _Rb_tree_impl : public _Node_allocator + struct _Rb_tree_impl + : public _Node_allocator + , public _Rb_tree_key_compare<_Key_compare> + , public _Rb_tree_header { - _Key_compare _M_key_compare; - _Rb_tree_node_base _M_header; - size_type _M_node_count; // Keeps track of size of tree. + typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; +#if __cplusplus < 201103L _Rb_tree_impl() - : _Node_allocator(), _M_key_compare(), _M_header(), - _M_node_count(0) - { _M_initialize(); } + { } +#else + _Rb_tree_impl() = default; + _Rb_tree_impl(_Rb_tree_impl&&) = default; +#endif - _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) - : _Node_allocator(__a), _M_key_compare(__comp), _M_header(), - _M_node_count(0) - { _M_initialize(); } + _Rb_tree_impl(const _Rb_tree_impl& __x) + : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x)) + , _Base_key_compare(__x._M_key_compare) + { } -#if __cplusplus >= 201103L +#if __cplusplus < 201103L + _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) + : _Node_allocator(__a), _Base_key_compare(__comp) + { } +#else _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) - : _Node_allocator(std::move(__a)), _M_key_compare(__comp), - _M_header(), _M_node_count(0) - { _M_initialize(); } + : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) + { } #endif - - void - _M_reset() - { - this->_M_header._M_parent = 0; - this->_M_header._M_left = &this->_M_header; - this->_M_header._M_right = &this->_M_header; - this->_M_node_count = 0; - } - - private: - void - _M_initialize() - { - this->_M_header._M_color = _S_red; - this->_M_header._M_parent = 0; - this->_M_header._M_left = &this->_M_header; - this->_M_header._M_right = &this->_M_header; - } }; _Rb_tree_impl<_Compare> _M_impl; @@ -735,6 +806,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Val, _Node_allocator>; + using insert_return_type = _Node_insert_return<iterator, node_type>; +#endif + pair<_Base_ptr, _Base_ptr> _M_get_insert_unique_pos(const key_type& __k); @@ -790,11 +866,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Link_type _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&); + template<typename _NodeGen> + _Link_type + _M_copy(const _Rb_tree& __x, _NodeGen& __gen) + { + _Link_type __root = _M_copy(__x._M_begin(), _M_end(), __gen); + _M_leftmost() = _S_minimum(__root); + _M_rightmost() = _S_maximum(__root); + _M_impl._M_node_count = __x._M_impl._M_node_count; + return __root; + } + _Link_type - _M_copy(_Const_Link_type __x, _Base_ptr __p) + _M_copy(const _Rb_tree& __x) { _Alloc_node __an(*this); - return _M_copy(__x, __p, __an); + return _M_copy(__x, __an); } void @@ -818,23 +905,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: // allocation/deallocation +#if __cplusplus < 201103L _Rb_tree() { } +#else + _Rb_tree() = default; +#endif _Rb_tree(const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_impl(__comp, _Node_allocator(__a)) { } _Rb_tree(const _Rb_tree& __x) - : _M_impl(__x._M_impl._M_key_compare, - _Alloc_traits::_S_select_on_copy(__x._M_get_Node_allocator())) + : _M_impl(__x._M_impl) { if (__x._M_root() != 0) - { - _M_root() = _M_copy(__x._M_begin(), _M_end()); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_impl._M_node_count = __x._M_impl._M_node_count; - } + _M_root() = _M_copy(__x); } #if __cplusplus >= 201103L @@ -846,21 +931,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a)) { if (__x._M_root() != nullptr) - { - _M_root() = _M_copy(__x._M_begin(), _M_end()); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_impl._M_node_count = __x._M_impl._M_node_count; - } + _M_root() = _M_copy(__x); } - _Rb_tree(_Rb_tree&& __x) - : _M_impl(__x._M_impl._M_key_compare, - std::move(__x._M_get_Node_allocator())) - { - if (__x._M_root() != 0) - _M_move_data(__x, std::true_type()); - } + _Rb_tree(_Rb_tree&&) = default; _Rb_tree(_Rb_tree&& __x, const allocator_type& __a) : _Rb_tree(std::move(__x), _Node_allocator(__a)) @@ -1031,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator erase(const_iterator __position) { + __glibcxx_assert(__position != end()); const_iterator __result = __position; ++__result; _M_erase_aux(__position); @@ -1042,6 +1117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator erase(iterator __position) { + __glibcxx_assert(__position != end()); iterator __result = __position; ++__result; _M_erase_aux(__position); @@ -1050,11 +1126,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else void erase(iterator __position) - { _M_erase_aux(__position); } + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } void erase(const_iterator __position) - { _M_erase_aux(__position); } + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } #endif size_type erase(const key_type& __x); @@ -1258,13 +1340,189 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: // Move elements from container with equal allocator. void - _M_move_data(_Rb_tree&, std::true_type); + _M_move_data(_Rb_tree& __x, std::true_type) + { _M_impl._M_move_data(__x._M_impl); } // Move elements from container with possibly non-equal allocator, // which might result in a copy not a move. void _M_move_data(_Rb_tree&, std::false_type); + + // Move assignment from container with equal allocator. + void + _M_move_assign(_Rb_tree&, std::true_type); + + // Move assignment from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_assign(_Rb_tree&, std::false_type); #endif + +#if __cplusplus > 201402L + public: + /// Re-insert an extracted node. + insert_return_type + _M_reinsert_node_unique(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + + auto __res = _M_get_insert_unique_pos(__nh._M_key()); + if (__res.second) + { + __ret.position + = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + else + { + __ret.node = std::move(__nh); + __ret.position = iterator(__res.first); + __ret.inserted = false; + } + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_equal(node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_equal_pos(__nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key()); + if (__res.second) + { + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + } + else + __ret = iterator(__res.first); + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Extract a node. + node_type + extract(const_iterator __pos) + { + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_const_cast()._M_node, _M_impl._M_header); + --_M_impl._M_node_count; + return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() }; + } + + /// Extract a node. + node_type + extract(const key_type& __k) + { + node_type __nh; + auto __pos = find(__k); + if (__pos != end()) + __nh = extract(const_iterator(__pos)); + return __nh; + } + + template<typename _Compare2> + using _Compatible_tree + = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>; + + template<typename, typename> + friend class _Rb_tree_merge_helper; + + /// Merge from a compatible container into one with unique keys. + template<typename _Compare2> + void + _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } + + /// Merge from a compatible container into one with equivalent keys. + template<typename _Compare2> + void + _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } +#endif // C++17 }; template<typename _Key, typename _Val, typename _KeyOfValue, @@ -1338,29 +1596,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Compare, typename _Alloc> void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_move_data(_Rb_tree& __x, std::true_type) - { - _M_root() = __x._M_root(); - _M_leftmost() = __x._M_leftmost(); - _M_rightmost() = __x._M_rightmost(); - _M_root()->_M_parent = _M_end(); - - __x._M_root() = 0; - __x._M_leftmost() = __x._M_end(); - __x._M_rightmost() = __x._M_end(); - - this->_M_impl._M_node_count = __x._M_impl._M_node_count; - __x._M_impl._M_node_count = 0; - } - - template<typename _Key, typename _Val, typename _KeyOfValue, - typename _Compare, typename _Alloc> - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: _M_move_data(_Rb_tree& __x, std::false_type) { if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) - _M_move_data(__x, std::true_type()); + _M_move_data(__x, std::true_type()); else { _Alloc_node __an(*this); @@ -1370,33 +1609,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto& __val = const_cast<value_type&>(__cval); return __an(std::move_if_noexcept(__val)); }; - _M_root() = _M_copy(__x._M_begin(), _M_end(), __lbd); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_impl._M_node_count = __x._M_impl._M_node_count; + _M_root() = _M_copy(__x, __lbd); } } template<typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, typename _Alloc> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + inline void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - operator=(_Rb_tree&& __x) - noexcept(_Alloc_traits::_S_nothrow_move() - && is_nothrow_move_assignable<_Compare>::value) + _M_move_assign(_Rb_tree& __x, true_type) { - _M_impl._M_key_compare = __x._M_impl._M_key_compare; - if (_Alloc_traits::_S_propagate_on_move_assign() - || _Alloc_traits::_S_always_equal() - || _M_get_Node_allocator() == __x._M_get_Node_allocator()) - { - clear(); - if (__x._M_root() != nullptr) - _M_move_data(__x, std::true_type()); - std::__alloc_on_move(_M_get_Node_allocator(), - __x._M_get_Node_allocator()); - return *this; - } + clear(); + if (__x._M_root() != nullptr) + _M_move_data(__x, std::true_type()); + std::__alloc_on_move(_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + return _M_move_assign(__x, true_type{}); // Try to move each node reusing existing nodes and copying __x nodes // structure. @@ -1410,12 +1647,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto& __val = const_cast<value_type&>(__cval); return __roan(std::move_if_noexcept(__val)); }; - _M_root() = _M_copy(__x._M_begin(), _M_end(), __lbd); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_impl._M_node_count = __x._M_impl._M_node_count; + _M_root() = _M_copy(__x, __lbd); __x.clear(); } + } + + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(_Rb_tree&& __x) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value) + { + _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare); + _M_move_assign(__x, __bool_constant<_Alloc_traits::_S_nothrow_move()>()); return *this; } @@ -1475,12 +1721,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_impl._M_reset(); _M_impl._M_key_compare = __x._M_impl._M_key_compare; if (__x._M_root() != 0) - { - _M_root() = _M_copy(__x._M_begin(), _M_end(), __roan); - _M_leftmost() = _S_minimum(_M_root()); - _M_rightmost() = _S_maximum(_M_root()); - _M_impl._M_node_count = __x._M_impl._M_node_count; - } + _M_root() = _M_copy(__x, __roan); } return *this; @@ -1755,26 +1996,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_root() == 0) { if (__t._M_root() != 0) - { - _M_root() = __t._M_root(); - _M_leftmost() = __t._M_leftmost(); - _M_rightmost() = __t._M_rightmost(); - _M_root()->_M_parent = _M_end(); - _M_impl._M_node_count = __t._M_impl._M_node_count; - - __t._M_impl._M_reset(); - } + _M_impl._M_move_data(__t._M_impl); } else if (__t._M_root() == 0) - { - __t._M_root() = _M_root(); - __t._M_leftmost() = _M_leftmost(); - __t._M_rightmost() = _M_rightmost(); - __t._M_root()->_M_parent = __t._M_end(); - __t._M_impl._M_node_count = _M_impl._M_node_count; - - _M_impl._M_reset(); - } + __t._M_impl._M_move_data(_M_impl); else { std::swap(_M_root(),__t._M_root()); @@ -2261,7 +2486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION clear(); else while (__first != __last) - erase(__first++); + _M_erase_aux(__first++); } template<typename _Key, typename _Val, typename _KeyOfValue, @@ -2272,7 +2497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { pair<iterator, iterator> __p = equal_range(__x); const size_type __old_size = size(); - erase(__p.first, __p.second); + _M_erase_aux(__p.first, __p.second); return __old_size - size(); } @@ -2365,6 +2590,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return true; } +#if __cplusplus > 201402L + // Allow access to internals of compatible _Rb_tree specializations. + template<typename _Key, typename _Val, typename _Sel, typename _Cmp1, + typename _Alloc, typename _Cmp2> + struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>; + + static auto& + _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree) + { return __tree._M_impl; } + }; +#endif // C++17 + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 6cfba13cb9..d0e2b2d33e 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -1,6 +1,6 @@ // Raw memory manipulators -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -56,6 +56,14 @@ #ifndef _STL_UNINITIALIZED_H #define _STL_UNINITIALIZED_H 1 +#if __cplusplus > 201402L +#include <utility> +#endif + +#if __cplusplus >= 201103L +#include <type_traits> +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -636,6 +644,99 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION allocator<_Tp>&) { return std::__uninitialized_default_n(__first, __n); } + template<bool _TrivialValueType> + struct __uninitialized_default_novalue_1 + { + template<typename _ForwardIterator> + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_1<true> + { + template<typename _ForwardIterator> + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + } + }; + + template<bool _TrivialValueType> + struct __uninitialized_default_novalue_n_1 + { + template<typename _ForwardIterator, typename _Size> + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_n_1<true> + { + template<typename _ForwardIterator, typename _Size> + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { return std::next(__first, __n); } + }; + + // __uninitialized_default_novalue + // Fills [first, last) with std::distance(first, last) default-initialized + // value_types(s). + template<typename _ForwardIterator> + inline void + __uninitialized_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::__uninitialized_default_novalue_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with n default-initialized value_type(s). + template<typename _ForwardIterator, typename _Size> + inline _ForwardIterator + __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return __uninitialized_default_novalue_n_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue_n(__first, __n); + } template<typename _InputIterator, typename _Size, typename _ForwardIterator> @@ -665,6 +766,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION random_access_iterator_tag) { return std::uninitialized_copy(__first, __first + __n, __result); } + template<typename _InputIterator, typename _Size, + typename _ForwardIterator> + pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return {__first, __cur}; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template<typename _RandomAccessIterator, typename _Size, + typename _ForwardIterator> + inline pair<_RandomAccessIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { + auto __second_res = uninitialized_copy(__first, __first + __n, __result); + auto __first_res = std::next(__first, __n); + return {__first_res, __second_res}; + } + /** * @brief Copies the range [first,first+n) into result. * @param __first An input iterator. @@ -680,8 +813,95 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __result) { return std::__uninitialized_copy_n(__first, __n, __result, std::__iterator_category(__first)); } + + template<typename _InputIterator, typename _Size, typename _ForwardIterator> + inline pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { + return + std::__uninitialized_copy_n_pair(__first, __n, __result, + std::__iterator_category(__first)); + } + #endif +#if __cplusplus > 201402L + template <typename _ForwardIterator> + inline void + uninitialized_default_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + __uninitialized_default_novalue(__first, __last); + } + + template <typename _ForwardIterator, typename _Size> + inline _ForwardIterator + uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_novalue_n(__first, __count); + } + + template <typename _ForwardIterator> + inline void + uninitialized_value_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + return __uninitialized_default(__first, __last); + } + + template <typename _ForwardIterator, typename _Size> + inline _ForwardIterator + uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_n(__first, __count); + } + + template <typename _InputIterator, typename _ForwardIterator> + inline _ForwardIterator + uninitialized_move(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + return std::uninitialized_copy + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); + } + + template <typename _InputIterator, typename _Size, typename _ForwardIterator> + inline pair<_InputIterator, _ForwardIterator> + uninitialized_move_n(_InputIterator __first, _Size __count, + _ForwardIterator __result) + { + auto __res = std::__uninitialized_copy_n_pair + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + __count, __result); + return {__res.first.base(), __res.second}; + } + + template <typename _Tp> + inline void + destroy_at(_Tp* __location) + { + std::_Destroy(__location); + } + + template <typename _ForwardIterator> + inline void + destroy(_ForwardIterator __first, _ForwardIterator __last) + { + std::_Destroy(__first, __last); + } + + template <typename _ForwardIterator, typename _Size> + inline _ForwardIterator + destroy_n(_ForwardIterator __first, _Size __count) + { + return std::_Destroy_n(__first, __count); + } + +#endif + + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 9b6d258f6c..fb882126cf 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1,6 +1,6 @@ // Vector implementation -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -63,6 +63,8 @@ #include <initializer_list> #endif +#include <debug/assertions.h> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER @@ -72,11 +74,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct _Vector_base { typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Tp>::other _Tp_alloc_type; + rebind<_Tp>::other _Tp_alloc_type; typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer; - struct _Vector_impl + struct _Vector_impl : public _Tp_alloc_type { pointer _M_start; @@ -105,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::swap(_M_end_of_storage, __x._M_end_of_storage); } }; - + public: typedef _Alloc allocator_type; @@ -213,31 +215,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class vector : protected _Vector_base<_Tp, _Alloc> { +#ifdef _GLIBCXX_CONCEPT_CHECKS // Concept requirements. - typedef typename _Alloc::value_type _Alloc_value_type; -#if __cplusplus < 201103L + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -#endif +# endif __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) - - typedef _Vector_base<_Tp, _Alloc> _Base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; +#endif + + typedef _Vector_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; public: - typedef _Tp value_type; - typedef typename _Base::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 _Tp value_type; + typedef typename _Base::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 __gnu_cxx::__normal_iterator<pointer, vector> iterator; typedef __gnu_cxx::__normal_iterator<const_pointer, vector> const_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; protected: using _Base::_M_allocate; @@ -312,15 +316,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief %Vector copy constructor. * @param __x A %vector of identical element and allocator types. * - * The newly-created %vector uses a copy of the allocation - * object used by @a __x. All the elements of @a __x are copied, - * but any extra memory in - * @a __x (for fast expansion) will not be copied. + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied + * (i.e. capacity() == size() in the new %vector). + * + * The newly-created %vector uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). */ vector(const vector& __x) : _Base(__x.size(), - _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator())) - { this->_M_impl._M_finish = + _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator())) + { + this->_M_impl._M_finish = std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, _M_get_Tp_allocator()); @@ -340,7 +347,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Copy constructor with alternative allocator vector(const vector& __x, const allocator_type& __a) : _Base(__x.size(), __a) - { this->_M_impl._M_finish = + { + this->_M_impl._M_finish = std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, _M_get_Tp_allocator()); @@ -400,16 +408,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - vector(_InputIterator __first, _InputIterator __last, + vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { _M_initialize_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - vector(_InputIterator __first, _InputIterator __last, + vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_initialize_dispatch(__first, __last, _Integral()); @@ -430,9 +438,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief %Vector assignment operator. * @param __x A %vector of identical element and allocator types. * - * All the elements of @a __x are copied, but any extra memory in - * @a __x (for fast expansion) will not be copied. Unlike the - * copy constructor, the allocator object is not copied. + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied. + * + * Whether the allocator is copied depends on the allocator traits. */ vector& operator=(const vector& __x); @@ -444,15 +453,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * The contents of @a __x are moved into this %vector (without copying, * if the allocators permit it). - * @a __x is a valid, but unspecified %vector. + * Afterwards @a __x is a valid, but unspecified %vector. + * + * Whether the allocator is moved depends on the allocator traits. */ vector& operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) { - constexpr bool __move_storage = - _Alloc_traits::_S_propagate_on_move_assign() - || _Alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign() + || _Alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); return *this; } @@ -465,12 +476,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %vector and * that the resulting %vector's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ vector& operator=(initializer_list<value_type> __l) { - this->assign(__l.begin(), __l.end()); + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); return *this; } #endif @@ -483,7 +495,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function fills a %vector with @a __n copies of the given * value. Note that the assignment completely changes the * %vector and that the resulting %vector's size is the same as - * the number of elements assigned. Old data may be lost. + * the number of elements assigned. */ void assign(size_type __n, const value_type& __val) @@ -499,19 +511,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %vector and * that the resulting %vector's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } #else template<typename _InputIterator> - void - assign(_InputIterator __first, _InputIterator __last) - { + void + assign(_InputIterator __first, _InputIterator __last) + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_assign_dispatch(__first, __last, _Integral()); @@ -528,11 +540,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %vector and * that the resulting %vector's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ void assign(initializer_list<value_type> __l) - { this->assign(__l.begin(), __l.end()); } + { + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + } #endif /// Get a copy of the memory allocation object. @@ -694,7 +709,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER resize(size_type __new_size, const value_type& __x) { if (__new_size > size()) - insert(end(), __new_size - size(), __x); + _M_fill_insert(end(), __new_size - size(), __x); else if (__new_size < size()) _M_erase_at_end(this->_M_impl._M_start + __new_size); } @@ -714,7 +729,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER resize(size_type __new_size, value_type __x = value_type()) { if (__new_size > size()) - insert(end(), __new_size - size(), __x); + _M_fill_insert(end(), __new_size - size(), __x); else if (__new_size < size()) _M_erase_at_end(this->_M_impl._M_start + __new_size); } @@ -778,7 +793,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference operator[](size_type __n) _GLIBCXX_NOEXCEPT - { return *(this->_M_impl._M_start + __n); } + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } /** * @brief Subscript access to the data contained in the %vector. @@ -793,7 +811,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { return *(this->_M_impl._M_start + __n); } + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } protected: /// Safety check used only from at(). @@ -823,7 +844,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER at(size_type __n) { _M_range_check(__n); - return (*this)[__n]; + return (*this)[__n]; } /** @@ -850,7 +871,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference front() _GLIBCXX_NOEXCEPT - { return *begin(); } + { + __glibcxx_requires_nonempty(); + return *begin(); + } /** * Returns a read-only (constant) reference to the data at the first @@ -858,7 +882,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference front() const _GLIBCXX_NOEXCEPT - { return *begin(); } + { + __glibcxx_requires_nonempty(); + return *begin(); + } /** * Returns a read/write reference to the data at the last @@ -866,15 +893,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference back() _GLIBCXX_NOEXCEPT - { return *(end() - 1); } - + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } + /** * Returns a read-only (constant) reference to the data at the * last element of the %vector. */ const_reference back() const _GLIBCXX_NOEXCEPT - { return *(end() - 1); } + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 464. Suggestion for new member functions in standard containers. @@ -883,19 +916,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Returns a pointer such that [data(), data() + size()) is a valid * range. For a non-empty %vector, data() == &front(). */ -#if __cplusplus >= 201103L _Tp* -#else - pointer -#endif data() _GLIBCXX_NOEXCEPT { return _M_data_ptr(this->_M_impl._M_start); } -#if __cplusplus >= 201103L const _Tp* -#else - const_pointer -#endif data() const _GLIBCXX_NOEXCEPT { return _M_data_ptr(this->_M_impl._M_start); } @@ -916,15 +941,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - __x); + __x); ++this->_M_impl._M_finish; } else -#if __cplusplus >= 201103L - _M_emplace_back_aux(__x); -#else - _M_insert_aux(end(), __x); -#endif + _M_realloc_insert(end(), __x); } #if __cplusplus >= 201103L @@ -933,8 +954,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { emplace_back(std::move(__x)); } template<typename... _Args> - void - emplace_back(_Args&&... __args); +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); #endif /** @@ -949,6 +974,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_back() _GLIBCXX_NOEXCEPT { + __glibcxx_requires_nonempty(); --this->_M_impl._M_finish; _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); } @@ -967,8 +993,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * std::list. */ template<typename... _Args> - iterator - emplace(const_iterator __position, _Args&&... __args); + iterator + emplace(const_iterator __position, _Args&&... __args) + { return _M_emplace_aux(__position, std::forward<_Args>(__args)...); } /** * @brief Inserts given value into %vector before specified iterator. @@ -1013,14 +1040,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator insert(const_iterator __position, value_type&& __x) - { return emplace(__position, std::move(__x)); } + { return _M_insert_rval(__position, std::move(__x)); } /** * @brief Inserts an initializer_list into the %vector. * @param __position An iterator into the %vector. * @param __l An initializer_list. * - * This function will insert copies of the data in the + * This function will insert copies of the data in the * initializer_list @a l into the %vector before the location * specified by @a position. * @@ -1030,7 +1057,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator insert(const_iterator __position, initializer_list<value_type> __l) - { return this->insert(__position, __l.begin(), __l.end()); } + { + auto __offset = __position - cbegin(); + _M_range_insert(begin() + __offset, __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } #endif #if __cplusplus >= 201103L @@ -1092,10 +1124,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> - iterator - insert(const_iterator __position, _InputIterator __first, + iterator + insert(const_iterator __position, _InputIterator __first, _InputIterator __last) - { + { difference_type __offset = __position - cbegin(); _M_insert_dispatch(begin() + __offset, __first, __last, __false_type()); @@ -1117,10 +1149,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * consider using std::list. */ template<typename _InputIterator> - void - insert(iterator __position, _InputIterator __first, + void + insert(iterator __position, _InputIterator __first, _InputIterator __last) - { + { // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); @@ -1190,13 +1222,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * (Three pointers, so it should be quite fast.) * Note that the global std::swap() function is specialized such that * std::swap(v1,v2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. */ void swap(vector& __x) _GLIBCXX_NOEXCEPT { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif this->_M_impl._M_swap_data(__x._M_impl); _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); + __x._M_get_Tp_allocator()); } /** @@ -1215,10 +1253,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * obtain @a n bytes of memory, and then copies [first,last) into it. */ template<typename _ForwardIterator> - pointer - _M_allocate_and_copy(size_type __n, + pointer + _M_allocate_and_copy(size_type __n, _ForwardIterator __first, _ForwardIterator __last) - { + { pointer __result = this->_M_allocate(__n); __try { @@ -1241,9 +1279,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) - { + void + _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) + { this->_M_impl._M_start = _M_allocate(static_cast<size_type>(__n)); this->_M_impl._M_end_of_storage = this->_M_impl._M_start + static_cast<size_type>(__n); @@ -1252,10 +1290,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by the range constructor to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) - { + { typedef typename std::iterator_traits<_InputIterator>:: iterator_category _IterCategory; _M_range_initialize(__first, __last, _IterCategory()); @@ -1263,10 +1301,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by the second initialize_dispatch above template<typename _InputIterator> - void - _M_range_initialize(_InputIterator __first, + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, std::input_iterator_tag) - { + { for (; __first != __last; ++__first) #if __cplusplus >= 201103L emplace_back(*__first); @@ -1277,10 +1315,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by the second initialize_dispatch above template<typename _ForwardIterator> - void - _M_range_initialize(_ForwardIterator __first, + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag) - { + { const size_type __n = std::distance(__first, __last); this->_M_impl._M_start = this->_M_allocate(__n); this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; @@ -1319,31 +1357,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } // Called by the range assign to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) - { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_assign_aux(__first, __last, _IterCategory()); - } + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } // Called by the second assign_dispatch above template<typename _InputIterator> - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, std::input_iterator_tag); // Called by the second assign_dispatch above template<typename _ForwardIterator> - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); // Called by assign(n,t), and the range assign when it turns out @@ -1351,7 +1385,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_fill_assign(size_type __n, const value_type& __val); - // Internal insert functions follow. // Called by the range insert to implement [23.1.1]/9 @@ -1359,32 +1392,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> - void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, __true_type) - { _M_fill_insert(__pos, __n, __val); } + { _M_fill_insert(__pos, __n, __val); } // Called by the range insert to implement [23.1.1]/9 template<typename _InputIterator> - void - _M_insert_dispatch(iterator __pos, _InputIterator __first, + void + _M_insert_dispatch(iterator __pos, _InputIterator __first, _InputIterator __last, __false_type) - { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_range_insert(__pos, __first, __last, _IterCategory()); + { + _M_range_insert(__pos, __first, __last, + std::__iterator_category(__first)); } // Called by the second insert_dispatch above template<typename _InputIterator> - void - _M_range_insert(iterator __pos, _InputIterator __first, + void + _M_range_insert(iterator __pos, _InputIterator __first, _InputIterator __last, std::input_iterator_tag); // Called by the second insert_dispatch above template<typename _ForwardIterator> - void - _M_range_insert(iterator __pos, _ForwardIterator __first, + void + _M_range_insert(iterator __pos, _ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); // Called by insert(p,n,x), and the range insert when it turns out to be @@ -1401,21 +1433,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_shrink_to_fit(); #endif - // Called by insert(p,x) #if __cplusplus < 201103L + // Called by insert(p,x) void _M_insert_aux(iterator __position, const value_type& __x); + + void + _M_realloc_insert(iterator __position, const value_type& __x); #else + // A value_type object constructed with _Alloc_traits::construct() + // and destroyed with _Alloc_traits::destroy(). + struct _Temporary_value + { + template<typename... _Args> + explicit + _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec) + { + _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(), + std::forward<_Args>(__args)...); + } + + ~_Temporary_value() + { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } + + value_type& + _M_val() { return *reinterpret_cast<_Tp*>(&__buf); } + + private: + pointer + _M_ptr() { return pointer_traits<pointer>::pointer_to(_M_val()); } + + vector* _M_this; + typename aligned_storage<sizeof(_Tp), alignof(_Tp)>::type __buf; + }; + + // Called by insert(p,x) and other functions when insertion needs to + // reallocate or move existing elements. _Arg is either _Tp& or _Tp. + template<typename _Arg> + void + _M_insert_aux(iterator __position, _Arg&& __arg); + template<typename... _Args> - void - _M_insert_aux(iterator __position, _Args&&... __args); + void + _M_realloc_insert(iterator __position, _Args&&... __args); + + // Either move-construct at the end, or forward to _M_insert_aux. + iterator + _M_insert_rval(const_iterator __position, value_type&& __v); + // Try to emplace at the end, otherwise forward to _M_insert_aux. template<typename... _Args> - void - _M_emplace_back_aux(_Args&&... __args); + iterator + _M_emplace_aux(const_iterator __position, _Args&&... __args); + + // Emplacing an rvalue of the correct type can use _M_insert_rval. + iterator + _M_emplace_aux(const_iterator __position, value_type&& __v) + { return _M_insert_rval(__position, std::move(__v)); } #endif - // Called by the latter. + // Called by _M_fill_insert, _M_insert_aux etc. size_type _M_check_len(size_type __n, const char* __s) const { @@ -1475,21 +1552,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #endif -#if __cplusplus >= 201103L template<typename _Up> _Up* - _M_data_ptr(_Up* __ptr) const + _M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT { return __ptr; } +#if __cplusplus >= 201103L template<typename _Ptr> typename std::pointer_traits<_Ptr>::element_type* _M_data_ptr(_Ptr __ptr) const { return empty() ? nullptr : std::__addressof(*__ptr); } #else + template<typename _Up> + _Up* + _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT + { return __ptr; } + template<typename _Ptr> - _Ptr + value_type* + _M_data_ptr(_Ptr __ptr) + { return __ptr.operator->(); } + + template<typename _Ptr> + const value_type* _M_data_ptr(_Ptr __ptr) const - { return __ptr; } + { return __ptr.operator->(); } #endif }; diff --git a/libstdc++-v3/include/bits/stream_iterator.h b/libstdc++-v3/include/bits/stream_iterator.h index f9c6ba67c5..552ed36d8b 100644 --- a/libstdc++-v3/include/bits/stream_iterator.h +++ b/libstdc++-v3/include/bits/stream_iterator.h @@ -1,6 +1,6 @@ // Stream iterators -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -66,7 +66,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Construct start of input stream iterator. istream_iterator(istream_type& __s) - : _M_stream(&__s) + : _M_stream(std::__addressof(__s)) { _M_read(); } istream_iterator(const istream_iterator& __obj) @@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } const _Tp* - operator->() const { return &(operator*()); } + operator->() const { return std::__addressof((operator*())); } istream_iterator& operator++() @@ -168,7 +168,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: /// Construct from an ostream. - ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {} + ostream_iterator(ostream_type& __s) + : _M_stream(std::__addressof(__s)), _M_string(0) {} /** * Construct from an ostream. diff --git a/libstdc++-v3/include/bits/streambuf.tcc b/libstdc++-v3/include/bits/streambuf.tcc index ff479ecd58..a8ac056c27 100644 --- a/libstdc++-v3/include/bits/streambuf.tcc +++ b/libstdc++-v3/include/bits/streambuf.tcc @@ -1,6 +1,6 @@ // Stream buffer classes -*- C++ -*- -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 2230e94612..f0451b12ce 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -1,6 +1,6 @@ // Streambuf iterators -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/string_view.tcc b/libstdc++-v3/include/bits/string_view.tcc new file mode 100644 index 0000000000..ffdcc30cae --- /dev/null +++ b/libstdc++-v3/include/bits/string_view.tcc @@ -0,0 +1,227 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2017 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/string_view.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string_view} + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW_TCC +#define _GLIBCXX_STRING_VIEW_TCC 1 + +#pragma GCC system_header + +#if __cplusplus <= 201402L +# include <bits/c++17_warning.h> +#else + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n == 0) + return __pos <= this->_M_len ? __pos : npos; + + if (__n <= this->_M_len) + { + for (; __pos <= this->_M_len - __n; ++__pos) + if (traits_type::eq(this->_M_str[__pos], __str[0]) + && traits_type::compare(this->_M_str + __pos + 1, + __str + 1, __n - 1) == 0) + return __pos; + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(_CharT __c, size_type __pos) const noexcept + { + size_type __ret = npos; + if (__pos < this->_M_len) + { + const size_type __n = this->_M_len - __pos; + const _CharT* __p = traits_type::find(this->_M_str + __pos, __n, __c); + if (__p) + __ret = __p - this->_M_str; + } + return __ret; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n <= this->_M_len) + { + __pos = std::min(size_type(this->_M_len - __n), __pos); + do + { + if (traits_type::compare(this->_M_str + __pos, __str, __n) == 0) + return __pos; + } + while (__pos-- > 0); + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size > 0) + { + if (--__size > __pos) + __size = __pos; + for (++__size; __size-- > 0; ) + if (traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_of(const _CharT* __str, size_type __pos, size_type __n) const + { + __glibcxx_requires_string_len(__str, __n); + for (; __n && __pos < this->_M_len; ++__pos) + { + const _CharT* __p = traits_type::find(__str, __n, + this->_M_str[__pos]); + if (__p) + return __pos; + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_of(const _CharT* __str, size_type __pos, size_type __n) const + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->size(); + if (__size && __n) + { + if (--__size > __pos) + __size = __pos; + do + { + if (traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size-- != 0); + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const + { + __glibcxx_requires_string_len(__str, __n); + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::find(__str, __n, this->_M_str[__pos])) + return __pos; + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(_CharT __c, size_type __pos) const noexcept + { + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::eq(this->_M_str[__pos], __c)) + return __pos; + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size--); + } + return npos; + } + + template<typename _CharT, typename _Traits> + typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + while (__size--); + } + return npos; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_STRING_VIEW_TCC diff --git a/libstdc++-v3/include/bits/stringfwd.h b/libstdc++-v3/include/bits/stringfwd.h index 98f7a43eb0..15db187f93 100644 --- a/libstdc++-v3/include/bits/stringfwd.h +++ b/libstdc++-v3/include/bits/stringfwd.h @@ -1,6 +1,6 @@ // <string> Forward declarations -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 diff --git a/libstdc++-v3/include/bits/uniform_int_dist.h b/libstdc++-v3/include/bits/uniform_int_dist.h index 393aa77b7f..af7ac14bcc 100644 --- a/libstdc++-v3/include/bits/uniform_int_dist.h +++ b/libstdc++-v3/include/bits/uniform_int_dist.h @@ -1,6 +1,6 @@ // Class template uniform_int_distribution -*- C++ -*- -// Copyright (C) 2009-2016 Free Software Foundation, Inc. +// Copyright (C) 2009-2017 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 @@ -36,10 +36,10 @@ namespace std _GLIBCXX_VISIBILITY(default) { -_GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __detail { +_GLIBCXX_BEGIN_NAMESPACE_VERSION /* Determine whether number is a power of 2. */ template<typename _Tp> inline bool @@ -47,8 +47,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return ((__x - 1) & __x) == 0; }; +_GLIBCXX_END_NAMESPACE_VERSION } +_GLIBCXX_BEGIN_NAMESPACE_VERSION + /** * @brief Uniform discrete distribution for random numbers. * A discrete random distribution on the range @f$[min, max]@f$ with equal @@ -58,7 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class uniform_int_distribution { static_assert(std::is_integral<_IntType>::value, - "template argument not an integral type"); + "template argument must be an integral type"); public: /** The type of the range of the distribution. */ @@ -88,6 +91,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + private: _IntType _M_a; _IntType _M_b; @@ -360,6 +367,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION *__f++ = __uctype(__urng()) - __urngmin + __param.a(); } + // operator!= and operator<< and operator>> are defined in <bits/random.h> + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index db31b54a43..a31cd67d6e 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -1,6 +1,6 @@ // unique_ptr implementation -*- C++ -*- -// Copyright (C) 2008-2016 Free Software Foundation, Inc. +// Copyright (C) 2008-2017 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 @@ -35,6 +35,8 @@ #include <type_traits> #include <utility> #include <tuple> +#include <bits/stl_function.h> +#include <bits/functional_hash.h> namespace std _GLIBCXX_VISIBILITY(default) { @@ -111,33 +113,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; - /// 20.7.1.2 unique_ptr for single objects. - template <typename _Tp, typename _Dp = default_delete<_Tp> > - class unique_ptr + template <typename _Tp, typename _Dp> + class __uniq_ptr_impl { - // use SFINAE to determine whether _Del::pointer exists - class _Pointer - { - template<typename _Up> - static typename _Up::pointer __test(typename _Up::pointer*); + template <typename _Up, typename _Ep, typename = void> + struct _Ptr + { + using type = _Up*; + }; - template<typename _Up> - static _Tp* __test(...); + template <typename _Up, typename _Ep> + struct + _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> + { + using type = typename remove_reference<_Ep>::type::pointer; + }; - typedef typename remove_reference<_Dp>::type _Del; + public: + using _DeleterConstraint = enable_if< + __and_<__not_<is_pointer<_Dp>>, + is_default_constructible<_Dp>>::value>; - public: - typedef decltype(__test<_Del>(0)) type; - }; + using pointer = typename _Ptr<_Tp, _Dp>::type; - typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type; - __tuple_type _M_t; + __uniq_ptr_impl() = default; + __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } - public: - typedef typename _Pointer::type pointer; - typedef _Tp element_type; - typedef _Dp deleter_type; + template<typename _Del> + __uniq_ptr_impl(pointer __p, _Del&& __d) + : _M_t(__p, std::forward<_Del>(__d)) { } + pointer& _M_ptr() { return std::get<0>(_M_t); } + pointer _M_ptr() const { return std::get<0>(_M_t); } + _Dp& _M_deleter() { return std::get<1>(_M_t); } + const _Dp& _M_deleter() const { return std::get<1>(_M_t); } + + private: + tuple<pointer, _Dp> _M_t; + }; + + /// 20.7.1.2 unique_ptr for single objects. + template <typename _Tp, typename _Dp = default_delete<_Tp>> + class unique_ptr + { + template <class _Up> + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_impl<_Tp, _Dp> _M_t; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; // helper template for detecting a safe conversion from another // unique_ptr @@ -155,10 +183,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 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"); } + template <typename _Up = _Dp, + typename = _DeleterConstraint<_Up>> + constexpr unique_ptr() noexcept + : _M_t() + { } /** Takes ownership of a pointer. * @@ -166,11 +195,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * 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"); } + template <typename _Up = _Dp, + typename = _DeleterConstraint<_Up>> + explicit + unique_ptr(pointer __p) noexcept + : _M_t(__p) + { } /** Takes ownership of a pointer. * @@ -198,7 +228,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "rvalue deleter bound to reference"); } /// Creates a unique_ptr that owns nothing. - constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } + template <typename _Up = _Dp, + typename = _DeleterConstraint<_Up>> + constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } // Move constructors. @@ -231,7 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Destructor, invokes the deleter if the stored pointer is not null. ~unique_ptr() noexcept { - auto& __ptr = std::get<0>(_M_t); + auto& __ptr = _M_t._M_ptr(); if (__ptr != nullptr) get_deleter()(__ptr); __ptr = pointer(); @@ -302,17 +334,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Return the stored pointer. pointer get() const noexcept - { return std::get<0>(_M_t); } + { return _M_t._M_ptr(); } /// Return a reference to the stored deleter. deleter_type& get_deleter() noexcept - { return std::get<1>(_M_t); } + { return _M_t._M_deleter(); } /// Return a reference to the stored deleter. const deleter_type& get_deleter() const noexcept - { return std::get<1>(_M_t); } + { return _M_t._M_deleter(); } /// Return @c true if the stored pointer is not null. explicit operator bool() const noexcept @@ -325,7 +357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION release() noexcept { pointer __p = get(); - std::get<0>(_M_t) = pointer(); + _M_t._M_ptr() = pointer(); return __p; } @@ -339,7 +371,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reset(pointer __p = pointer()) noexcept { using std::swap; - swap(std::get<0>(_M_t), __p); + swap(_M_t._M_ptr(), __p); if (__p != pointer()) get_deleter()(__p); } @@ -364,23 +396,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Dp> class unique_ptr<_Tp[], _Dp> { - // use SFINAE to determine whether _Del::pointer exists - class _Pointer - { - template<typename _Up> - static typename _Up::pointer __test(typename _Up::pointer*); - - template<typename _Up> - static _Tp* __test(...); - - typedef typename remove_reference<_Dp>::type _Del; + template <typename _Up> + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; - public: - typedef decltype(__test<_Del>(0)) type; - }; - - typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type; - __tuple_type _M_t; + __uniq_ptr_impl<_Tp, _Dp> _M_t; template<typename _Up> using __remove_cv = typename remove_cv<_Up>::type; @@ -391,11 +411,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = __and_< is_base_of<_Tp, _Up>, __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; - public: - typedef typename _Pointer::type pointer; - typedef _Tp element_type; - typedef _Dp deleter_type; + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; // helper template for detecting a safe conversion from another // unique_ptr @@ -429,10 +448,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 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"); } + template <typename _Up = _Dp, + typename = _DeleterConstraint<_Up>> + constexpr unique_ptr() noexcept + : _M_t() + { } /** Takes ownership of a pointer. * @@ -442,13 +462,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The deleter will be value-initialized. */ template<typename _Up, - typename = typename enable_if< + typename _Vp = _Dp, + typename = _DeleterConstraint<_Vp>, + typename = typename enable_if< __safe_conversion_raw<_Up>::value, bool>::type> - explicit - unique_ptr(_Up __p) noexcept - : _M_t(__p, deleter_type()) - { static_assert(!is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + explicit + unique_ptr(_Up __p) noexcept + : _M_t(__p) + { } /** Takes ownership of a pointer. * @@ -488,7 +509,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _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 = _Dp, + typename = _DeleterConstraint<_Up>> + constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } template<typename _Up, typename _Ep, typename = _Require<__safe_conversion_up<_Up, _Ep>>> @@ -499,7 +522,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Destructor, invokes the deleter if the stored pointer is not null. ~unique_ptr() { - auto& __ptr = std::get<0>(_M_t); + auto& __ptr = _M_t._M_ptr(); if (__ptr != nullptr) get_deleter()(__ptr); __ptr = pointer(); @@ -562,17 +585,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Return the stored pointer. pointer get() const noexcept - { return std::get<0>(_M_t); } + { return _M_t._M_ptr(); } /// Return a reference to the stored deleter. deleter_type& get_deleter() noexcept - { return std::get<1>(_M_t); } + { return _M_t._M_deleter(); } /// Return a reference to the stored deleter. const deleter_type& get_deleter() const noexcept - { return std::get<1>(_M_t); } + { return _M_t._M_deleter(); } /// Return @c true if the stored pointer is not null. explicit operator bool() const noexcept @@ -585,7 +608,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION release() noexcept { pointer __p = get(); - std::get<0>(_M_t) = pointer(); + _M_t._M_ptr() = pointer(); return __p; } @@ -610,10 +633,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void reset(_Up __p) noexcept { + pointer __ptr = __p; using std::swap; - swap(std::get<0>(_M_t), __p); - if (__p != nullptr) - get_deleter()(__p); + swap(_M_t._M_ptr(), __ptr); + if (__ptr != nullptr) + get_deleter()(__ptr); } void reset(nullptr_t = nullptr) noexcept @@ -635,11 +659,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template<typename _Tp, typename _Dp> - inline void + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Dp>::value>::type +#else + void +#endif swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) noexcept { __x.swap(__y); } +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template<typename _Tp, typename _Dp> + typename enable_if<!__is_swappable<_Dp>::value>::type + swap(unique_ptr<_Tp, _Dp>&, + unique_ptr<_Tp, _Dp>&) = delete; +#endif + template<typename _Tp, typename _Dp, typename _Up, typename _Ep> inline bool @@ -754,7 +791,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// std::hash specialization for unique_ptr. template<typename _Tp, typename _Dp> struct hash<unique_ptr<_Tp, _Dp>> - : public __hash_base<size_t, unique_ptr<_Tp, _Dp>> + : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, + private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> { size_t operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index d6f5ab7af0..4ef30ccccd 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -1,6 +1,6 @@ // unordered_map implementation -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -68,6 +68,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; + template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> + class unordered_multimap; + /** * @brief A standard container composed of unique keys (containing * at most one of each key value) that associates values of another type @@ -126,6 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; //@} +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + //construct/destroy/copy /// Default constructor. @@ -274,7 +282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %unordered_map and * that the resulting %unordered_map's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ unordered_map& operator=(initializer_list<value_type> __l) @@ -283,8 +291,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } - /// Returns the allocator object with which the %unordered_map was - /// constructed. + /// Returns the allocator object used by the %unordered_map. allocator_type get_allocator() const noexcept { return _M_h.get_allocator(); } @@ -410,8 +417,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER emplace_hint(const_iterator __pos, _Args&&... __args) { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } - #if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } + #define __cpp_lib_unordered_map_try_emplace 201411 /** * @brief Attempts to build and insert a std::pair into the @@ -525,7 +554,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::forward<_Args>(__args)...)); return __i; } -#endif +#endif // C++17 //@{ /** @@ -818,6 +847,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } +#if __cplusplus > 201402L + template<typename, typename, typename> + friend class _Hash_merge_helper; + + template<typename _H2, typename _P2> + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template<typename _H2, typename _P2> + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + // observers. /// Returns the hash functor object with which the %unordered_map was @@ -1053,8 +1113,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Key1, typename _Tp1, typename _Hash1, typename _Pred1, typename _Alloc1> friend bool - operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&, - const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); + operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&, + const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); }; /** @@ -1115,6 +1175,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; //@} +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + //construct/destroy/copy /// Default constructor. @@ -1258,12 +1322,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief %Unordered_multimap list assignment operator. * @param __l An initializer_list. * - * This function fills an %unordered_multimap with copies of the elements - * in the initializer list @a __l. + * This function fills an %unordered_multimap with copies of the + * elements in the initializer list @a __l. * * Note that the assignment completely changes the %unordered_multimap * and that the resulting %unordered_multimap's size is the same as the - * number of elements assigned. Old data may be lost. + * number of elements assigned. */ unordered_multimap& operator=(initializer_list<value_type> __l) @@ -1272,8 +1336,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } - /// Returns the allocator object with which the %unordered_multimap was - /// constructed. + /// Returns the allocator object used by the %unordered_multimap. allocator_type get_allocator() const noexcept { return _M_h.get_allocator(); } @@ -1470,6 +1533,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(initializer_list<value_type> __l) { _M_h.insert(__l); } +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + //@{ /** * @brief Erases an element from an %unordered_multimap. @@ -1553,6 +1641,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } +#if __cplusplus > 201402L + template<typename, typename, typename> + friend class _Hash_merge_helper; + + template<typename _H2, typename _P2> + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper<unordered_multimap, _H2, _P2>; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template<typename _H2, typename _P2> + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper<unordered_multimap, _H2, _P2>; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + // observers. /// Returns the hash functor object with which the %unordered_multimap @@ -1788,6 +1909,59 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return !(__x == __y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::unordered_map access to internals of compatible maps. + template<typename _Key, typename _Val, typename _Hash1, typename _Eq1, + typename _Alloc, typename _Hash2, typename _Eq2> + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template<typename... _Tp> + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template<typename... _Tp> + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; + + // Allow std::unordered_multimap access to internals of compatible maps. + template<typename _Key, typename _Val, typename _Hash1, typename _Eq1, + typename _Alloc, typename _Hash2, typename _Eq2> + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template<typename... _Tp> + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template<typename... _Tp> + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } // namespace std #endif /* _UNORDERED_MAP_H */ diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index 3efd1f94c7..85c2562f89 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -1,6 +1,6 @@ // unordered_set implementation -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -65,6 +65,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; + template<class _Value, class _Hash, class _Pred, class _Alloc> + class unordered_multiset; + /** * @brief A standard container composed of unique keys (containing * at most one of each key value) in which the elements' keys are @@ -120,6 +123,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; //@} +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + // construct/destroy/copy /// Default constructor. @@ -268,7 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %unordered_set and * that the resulting %unordered_set's size is the same as the number - * of elements assigned. Old data may be lost. + * of elements assigned. */ unordered_set& operator=(initializer_list<value_type> __l) @@ -277,8 +285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } - /// Returns the allocator object with which the %unordered_set was - /// constructed. + /// Returns the allocator object used by the %unordered_set. allocator_type get_allocator() const noexcept { return _M_h.get_allocator(); } @@ -471,6 +478,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(initializer_list<value_type> __l) { _M_h.insert(__l); } +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } +#endif // C++17 + //@{ /** * @brief Erases an element from an %unordered_set. @@ -553,6 +585,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } +#if __cplusplus > 201402L + template<typename, typename, typename> + friend class _Hash_merge_helper; + + template<typename _H2, typename _P2> + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper<unordered_set, _H2, _P2>; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template<typename _H2, typename _P2> + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper<unordered_set, _H2, _P2>; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + // observers. /// Returns the hash functor object with which the %unordered_set was @@ -794,6 +857,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; //@} +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + // construct/destroy/copy /// Default constructor. @@ -942,7 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Note that the assignment completely changes the %unordered_multiset * and that the resulting %unordered_multiset's size is the same as the - * number of elements assigned. Old data may be lost. + * number of elements assigned. */ unordered_multiset& operator=(initializer_list<value_type> __l) @@ -951,8 +1018,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } - /// Returns the allocator object with which the %unordered_multiset was - /// constructed. + /// Returns the allocator object used by the %unordered_multiset. allocator_type get_allocator() const noexcept { return _M_h.get_allocator(); } @@ -1123,6 +1189,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(initializer_list<value_type> __l) { _M_h.insert(__l); } +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + //@{ /** * @brief Erases an element from an %unordered_multiset. @@ -1210,6 +1301,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } +#if __cplusplus > 201402L + template<typename, typename, typename> + friend class _Hash_merge_helper; + + template<typename _H2, typename _P2> + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper<unordered_multiset, _H2, _P2>; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template<typename _H2, typename _P2> + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper<unordered_multiset, _H2, _P2>; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template<typename _H2, typename _P2> + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + // observers. /// Returns the hash functor object with which the %unordered_multiset @@ -1431,6 +1555,58 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return !(__x == __y); } _GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Allow std::unordered_set access to internals of compatible sets. + template<typename _Val, typename _Hash1, typename _Eq1, typename _Alloc, + typename _Hash2, typename _Eq2> + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_set<_Val, _Hash1, _Eq1, _Alloc>, _Hash2, _Eq2> + { + private: + template<typename... _Tp> + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template<typename... _Tp> + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_set<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; + + // Allow std::unordered_multiset access to internals of compatible sets. + template<typename _Val, typename _Hash1, typename _Eq1, typename _Alloc, + typename _Hash2, typename _Eq2> + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template<typename... _Tp> + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template<typename... _Tp> + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; +_GLIBCXX_END_NAMESPACE_VERSION +#endif // C++17 + } // namespace std #endif /* _UNORDERED_SET_H */ diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h index b1ff58a294..89d4e43565 100644 --- a/libstdc++-v3/include/bits/uses_allocator.h +++ b/libstdc++-v3/include/bits/uses_allocator.h @@ -1,6 +1,6 @@ // Uses-allocator Construction -*- C++ -*- -// Copyright (C) 2010-2016 Free Software Foundation, Inc. +// Copyright (C) 2010-2017 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 @@ -45,7 +45,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// [allocator.tag] struct allocator_arg_t { explicit allocator_arg_t() = default; }; - constexpr allocator_arg_t allocator_arg = allocator_arg_t(); + _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = + allocator_arg_t(); template<typename _Tp, typename _Alloc, typename = __void_t<>> struct __uses_allocator_helper @@ -108,6 +109,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __ret._M_a = std::__addressof(__a); return __ret; } +#if __cplusplus > 201402L + template <typename _Tp, typename _Alloc> + inline constexpr bool uses_allocator_v = + uses_allocator<_Tp, _Alloc>::value; +#endif // C++17 + + template<template<typename...> class _Predicate, + typename _Tp, typename _Alloc, typename... _Args> + struct __is_uses_allocator_predicate + : conditional<uses_allocator<_Tp, _Alloc>::value, + __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, + _Predicate<_Tp, _Args..., _Alloc>>, + _Predicate<_Tp, _Args...>>::type { }; + + template<typename _Tp, typename _Alloc, typename... _Args> + struct __is_uses_allocator_constructible + : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...> + { }; + +#if __cplusplus >= 201402L + template<typename _Tp, typename _Alloc, typename... _Args> + _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = + __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template<typename _Tp, typename _Alloc, typename... _Args> + struct __is_nothrow_uses_allocator_constructible + : __is_uses_allocator_predicate<is_nothrow_constructible, + _Tp, _Alloc, _Args...> + { }; + + +#if __cplusplus >= 201402L + template<typename _Tp, typename _Alloc, typename... _Args> + _GLIBCXX17_INLINE constexpr bool + __is_nothrow_uses_allocator_constructible_v = + __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template<typename _Tp, typename... _Args> + void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } + + template<typename _Tp, typename _Alloc, typename... _Args> + void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { + ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, + std::forward<_Args>(__args)...); + } + + template<typename _Tp, typename _Alloc, typename... _Args> + void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } + + template<typename _Tp, typename _Alloc, typename... _Args> + void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, + _Args&&... __args) + { + __uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a), + __ptr, std::forward<_Args>(__args)...); + } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/valarray_after.h b/libstdc++-v3/include/bits/valarray_after.h index 53dab52880..54ba7fed61 100644 --- a/libstdc++-v3/include/bits/valarray_after.h +++ b/libstdc++-v3/include/bits/valarray_after.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- internal _Meta class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h index d6f8e7a23f..f169edd972 100644 --- a/libstdc++-v3/include/bits/valarray_array.h +++ b/libstdc++-v3/include/bits/valarray_array.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- internal _Array helper class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/valarray_array.tcc b/libstdc++-v3/include/bits/valarray_array.tcc index 812d94b454..9879c52810 100644 --- a/libstdc++-v3/include/bits/valarray_array.tcc +++ b/libstdc++-v3/include/bits/valarray_array.tcc @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- internal _Array helper class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/valarray_before.h b/libstdc++-v3/include/bits/valarray_before.h index 86136f438c..67603e1099 100644 --- a/libstdc++-v3/include/bits/valarray_before.h +++ b/libstdc++-v3/include/bits/valarray_before.h @@ -1,6 +1,6 @@ // The template and inlines for the -*- C++ -*- internal _Meta class. -// Copyright (C) 1997-2016 Free Software Foundation, Inc. +// Copyright (C) 1997-2017 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 diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 715b83eb67..8d688661c8 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -1,6 +1,6 @@ // Vector implementation (out of line) -*- C++ -*- -// Copyright (C) 2001-2016 Free Software Foundation, Inc. +// Copyright (C) 2001-2017 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 @@ -87,7 +87,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _Tp, typename _Alloc> template<typename... _Args> +#if __cplusplus > 201402L + typename vector<_Tp, _Alloc>::reference +#else void +#endif vector<_Tp, _Alloc>:: emplace_back(_Args&&... __args) { @@ -98,7 +102,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ++this->_M_impl._M_finish; } else - _M_emplace_back_aux(std::forward<_Args>(__args)...); + _M_realloc_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif } #endif @@ -112,27 +119,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif { const size_type __n = __position - begin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage - && __position == end()) - { - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); - ++this->_M_impl._M_finish; - } - else - { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == end()) + { + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + } + else + { #if __cplusplus >= 201103L - const auto __pos = begin() + (__position - cbegin()); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - _Tp __x_copy = __x; - _M_insert_aux(__pos, std::move(__x_copy)); - } - else - _M_insert_aux(__pos, __x); + const auto __pos = begin() + (__position - cbegin()); + // __x could be an existing element of this vector, so make a + // copy of it before _M_insert_aux moves elements around. + _Temporary_value __x_copy(this, __x); + _M_insert_aux(__pos, std::move(__x_copy._M_val())); #else _M_insert_aux(__position, __x); #endif - } + } + else +#if __cplusplus >= 201103L + _M_realloc_insert(begin() + (__position - cbegin()), __x); +#else + _M_realloc_insert(__position, __x); +#endif + return iterator(this->_M_impl._M_start + __n); } @@ -256,7 +268,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__first == __last) _M_erase_at_end(__cur); else - insert(end(), __first, __last); + _M_range_insert(end(), __first, __last, + std::__iterator_category(__first)); } template<typename _Tp, typename _Alloc> @@ -296,30 +309,60 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _Tp, typename _Alloc> - template<typename... _Args> - typename vector<_Tp, _Alloc>::iterator - vector<_Tp, _Alloc>:: - emplace(const_iterator __position, _Args&&... __args) - { - const size_type __n = __position - begin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage - && __position == end()) + auto + vector<_Tp, _Alloc>:: + _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) { _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - std::forward<_Args>(__args)...); + std::move(__v)); ++this->_M_impl._M_finish; } else - _M_insert_aux(begin() + (__position - cbegin()), - std::forward<_Args>(__args)...); + _M_insert_aux(begin() + __n, std::move(__v)); + else + _M_realloc_insert(begin() + __n, std::move(__v)); + + return iterator(this->_M_impl._M_start + __n); + } + + template<typename _Tp, typename _Alloc> + template<typename... _Args> + auto + vector<_Tp, _Alloc>:: + _M_emplace_aux(const_iterator __position, _Args&&... __args) + -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + } + else + { + // We need to construct a temporary because something in __args... + // could alias one of the elements of the container and so we + // need to use it before _M_insert_aux moves elements around. + _Temporary_value __tmp(this, std::forward<_Args>(__args)...); + _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); + } + else + _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...); + return iterator(this->_M_impl._M_start + __n); } template<typename _Tp, typename _Alloc> - template<typename... _Args> + template<typename _Arg> void vector<_Tp, _Alloc>:: - _M_insert_aux(iterator __position, _Args&&... __args) + _M_insert_aux(iterator __position, _Arg&& __arg) #else template<typename _Tp, typename _Alloc> void @@ -327,77 +370,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_insert_aux(iterator __position, const _Tp& __x) #endif { - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - _GLIBCXX_MOVE(*(this->_M_impl._M_finish - - 1))); - ++this->_M_impl._M_finish; + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + _GLIBCXX_MOVE(*(this->_M_impl._M_finish + - 1))); + ++this->_M_impl._M_finish; #if __cplusplus < 201103L - _Tp __x_copy = __x; + _Tp __x_copy = __x; #endif - _GLIBCXX_MOVE_BACKWARD3(__position.base(), - this->_M_impl._M_finish - 2, - this->_M_impl._M_finish - 1); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + this->_M_impl._M_finish - 2, + this->_M_impl._M_finish - 1); #if __cplusplus < 201103L - *__position = __x_copy; -#else - *__position = _Tp(std::forward<_Args>(__args)...); -#endif - } - else - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_insert_aux"); - const size_type __elems_before = __position - begin(); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - // The order of the three operations is dictated by the C++0x - // case, where the moves could alter a new element belonging - // to the existing vector. This is an issue only for callers - // taking the element by const lvalue ref (see 23.1/13). - _Alloc_traits::construct(this->_M_impl, - __new_start + __elems_before, -#if __cplusplus >= 201103L - std::forward<_Args>(__args)...); + *__position = __x_copy; #else - __x); + *__position = std::forward<_Arg>(__arg); #endif - __new_finish = pointer(); - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - - ++__new_finish; - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, - __new_finish, _M_get_Tp_allocator()); - } - __catch(...) - { - if (!__new_finish) - _Alloc_traits::destroy(this->_M_impl, - __new_start + __elems_before); - else - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } } #if __cplusplus >= 201103L @@ -405,44 +392,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename... _Args> void vector<_Tp, _Alloc>:: - _M_emplace_back_aux(_Args&&... __args) - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_emplace_back_aux"); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - _Alloc_traits::construct(this->_M_impl, __new_start + size(), - std::forward<_Args>(__args)...); - __new_finish = pointer(); + _M_realloc_insert(iterator __position, _Args&&... __args) +#else + template<typename _Tp, typename _Alloc> + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, const _Tp& __x) +#endif + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_realloc_insert"); + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // The order of the three operations is dictated by the C++11 + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by lvalue ref (see last bullet of C++11 + // [res.on.arguments]). + _Alloc_traits::construct(this->_M_impl, + __new_start + __elems_before, +#if __cplusplus >= 201103L + std::forward<_Args>(__args)...); +#else + __x); +#endif + __new_finish = pointer(); - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, this->_M_impl._M_finish, - __new_start, _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); - ++__new_finish; - } - __catch(...) - { - if (!__new_finish) - _Alloc_traits::destroy(this->_M_impl, __new_start + size()); - else - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } -#endif + ++__new_finish; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + if (!__new_finish) + _Alloc_traits::destroy(this->_M_impl, + __new_start + __elems_before); + else + std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } template<typename _Tp, typename _Alloc> void @@ -454,7 +463,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { +#if __cplusplus < 201103L value_type __x_copy = __x; +#else + _Temporary_value __tmp(this, __x); + value_type& __x_copy = __tmp._M_val(); +#endif const size_type __elems_after = end() - __position; pointer __old_finish(this->_M_impl._M_finish); if (__elems_after > __n) @@ -492,7 +506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer __new_finish(__new_start); __try { - // See _M_insert_aux above. + // See _M_realloc_insert above. std::__uninitialized_fill_n_a(__new_start + __elems_before, __n, __x, _M_get_Tp_allocator()); @@ -701,9 +715,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Bit_pointer __q = this->_M_allocate(__n); iterator __start(std::__addressof(*__q), 0); - this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), __start); + iterator __finish(_M_copy_aligned(begin(), end(), __start)); this->_M_deallocate(); this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; this->_M_impl._M_end_of_storage = __q + _S_nword(__n); } @@ -729,11 +744,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator __start(std::__addressof(*__q), 0); iterator __i = _M_copy_aligned(begin(), __position, __start); std::fill(__i, __i + difference_type(__n), __x); - this->_M_impl._M_finish = std::copy(__position, end(), - __i + difference_type(__n)); + iterator __finish = std::copy(__position, end(), + __i + difference_type(__n)); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; } } @@ -763,10 +779,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator __start(std::__addressof(*__q), 0); iterator __i = _M_copy_aligned(begin(), __position, __start); __i = std::copy(__first, __last, __i); - this->_M_impl._M_finish = std::copy(__position, end(), __i); + iterator __finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; } } } @@ -791,10 +808,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator __start(std::__addressof(*__q), 0); iterator __i = _M_copy_aligned(begin(), __position, __start); *__i++ = __x; - this->_M_impl._M_finish = std::copy(__position, end(), __i); + iterator __finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; } } |