| // <flat_set> -*- C++ -*- | |
| // Copyright The GNU Toolchain Authors. | |
| // | |
| // 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/flat_set | |
| * This is a Standard C++ Library header. | |
| */ | |
| #ifndef _GLIBCXX_FLAT_SET | |
| #define _GLIBCXX_FLAT_SET 1 | |
| #ifdef _GLIBCXX_SYSHDR | |
| #pragma GCC system_header | |
| #endif | |
| #define __glibcxx_want_constexpr_flat_set | |
| #define __glibcxx_want_flat_set | |
| #include <bits/version.h> | |
| #ifdef __cpp_lib_flat_set // >= C++23 | |
| #include <compare> | |
| #include <initializer_list> | |
| #include <exception> | |
| #include <functional> // not_fn | |
| #include <optional> | |
| #include <type_traits> | |
| #include <vector> | |
| #include <bits/stl_algo.h> | |
| #include <bits/stl_function.h> // less | |
| #include <bits/stl_pair.h> | |
| #include <bits/uses_allocator_args.h> // make_obj_using_allocator | |
| #ifdef _GLIBCXX_DEBUG | |
| # include <bits/ranges_algo.h> // ranges::is_sorted | |
| #endif | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| template<typename _Key, typename _Compare, | |
| typename _KeyContainer> | |
| class flat_set; | |
| template<typename _Key, typename _Compare, | |
| typename _KeyContainer> | |
| class flat_multiset; | |
| template<typename _Key, typename _Compare, typename _KeyContainer, bool _Multi> | |
| class _Flat_set_impl | |
| { | |
| static_assert(is_same_v<_Key, typename _KeyContainer::value_type>); | |
| using _Derived = __conditional_t<_Multi, | |
| flat_multiset<_Key, _Compare, _KeyContainer>, | |
| flat_set<_Key, _Compare, _KeyContainer>>; | |
| using __sorted_t = __conditional_t<_Multi, sorted_equivalent_t, sorted_unique_t>; | |
| public: | |
| using key_type = _Key; | |
| using value_type = _Key; | |
| using key_compare = _Compare; | |
| using value_compare = _Compare; | |
| using reference = value_type&; | |
| using const_reference = const value_type&; | |
| using size_type = typename _KeyContainer::size_type; | |
| using difference_type = typename _KeyContainer::difference_type; | |
| using iterator = typename _KeyContainer::const_iterator; | |
| using const_iterator = typename _KeyContainer::const_iterator; | |
| using reverse_iterator = std::reverse_iterator<iterator>; | |
| using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
| using container_type = _KeyContainer; | |
| private: | |
| using __emplace_result_t = __conditional_t<_Multi, iterator, pair<iterator, bool>>; | |
| struct _ClearGuard | |
| { | |
| container_type* _M_cont; | |
| _GLIBCXX26_CONSTEXPR | |
| _ClearGuard(container_type& __cont) | |
| : _M_cont(std::__addressof(__cont)) | |
| { } | |
| _GLIBCXX26_CONSTEXPR | |
| ~_ClearGuard() | |
| { | |
| if (_M_cont) | |
| _M_cont->clear(); | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| _M_disable() | |
| { _M_cont = nullptr; } | |
| }; | |
| _GLIBCXX26_CONSTEXPR | |
| _ClearGuard | |
| _M_make_clear_guard() | |
| { return _ClearGuard{this->_M_cont}; } | |
| public: | |
| // constructors | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl() : _Flat_set_impl(key_compare()) { } | |
| _GLIBCXX26_CONSTEXPR | |
| explicit | |
| _Flat_set_impl(const key_compare& __comp) | |
| : _M_cont(), _M_comp(__comp) | |
| { } | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(container_type __cont, const key_compare& __comp = key_compare()) | |
| : _M_cont(std::move(__cont)), _M_comp(__comp) | |
| { _M_sort_uniq(); } | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t, | |
| container_type __cont, const key_compare& __comp = key_compare()) | |
| : _M_cont(std::move(__cont)), _M_comp(__comp) | |
| { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); } | |
| template<__has_input_iter_cat _InputIterator> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(_InputIterator __first, _InputIterator __last, | |
| const key_compare& __comp = key_compare()) | |
| : _M_cont(), _M_comp(__comp) | |
| { insert(__first, __last); } | |
| template<__has_input_iter_cat _InputIterator> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| _InputIterator __first, _InputIterator __last, | |
| const key_compare& __comp = key_compare()) | |
| : _M_cont(), _M_comp(__comp) | |
| { insert(__s, __first, __last); } | |
| template<__detail::__container_compatible_range<value_type> _Rg> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(from_range_t, _Rg&& __rg) | |
| : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), key_compare()) | |
| { } | |
| template<__detail::__container_compatible_range<value_type> _Rg> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(from_range_t, _Rg&& __rg, const key_compare& __comp) | |
| : _Flat_set_impl(__comp) | |
| { insert_range(std::forward<_Rg>(__rg)); } | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(initializer_list<value_type> __il, | |
| const key_compare& __comp = key_compare()) | |
| : _Flat_set_impl(__il.begin(), __il.end(), __comp) | |
| { } | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| initializer_list<value_type> __il, | |
| const key_compare& __comp = key_compare()) | |
| : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp) | |
| { } | |
| // constructors with allocators | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| explicit | |
| _Flat_set_impl(const _Alloc& __a) | |
| : _Flat_set_impl(key_compare(), __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(const key_compare& __comp, const _Alloc& __a) | |
| : _M_cont(std::make_obj_using_allocator<container_type>(__a)), | |
| _M_comp(__comp) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(const container_type& __cont, const _Alloc& __a) | |
| : _Flat_set_impl(__cont, key_compare(), __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(const container_type& __cont, const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)), | |
| _M_comp(__comp) | |
| { _M_sort_uniq(); } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, const container_type& __cont, const _Alloc& __a) | |
| : _Flat_set_impl(__s, __cont, key_compare(), __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t, const container_type& __cont, const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)), | |
| _M_comp(__comp) | |
| { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(const _Derived& __x, const _Alloc& __a) | |
| : _M_cont(std::make_obj_using_allocator<container_type>(__a, __x._M_cont)), | |
| _M_comp(__x._M_comp) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(_Derived&& __x, const _Alloc& __a) | |
| : _M_cont(std::make_obj_using_allocator<container_type>(__a, std::move(__x._M_cont))), | |
| _M_comp(__x._M_comp) | |
| { } | |
| template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(_InputIterator __first, _InputIterator __last, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(std::move(__first), std::move(__last), key_compare(), __a) | |
| { } | |
| template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(_InputIterator __first, _InputIterator __last, | |
| const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__comp, __a) | |
| { insert(__first, __last); } | |
| template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| _InputIterator __first, _InputIterator __last, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__s, std::move(__first), std::move(__last), key_compare(), __a) | |
| { } | |
| template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| _InputIterator __first, _InputIterator __last, | |
| const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__comp, __a) | |
| { insert(__s, __first, __last); } | |
| template<__detail::__container_compatible_range<value_type> _Rg, | |
| __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(from_range_t, _Rg&& __rg, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), key_compare(), __a) | |
| { } | |
| template<__detail::__container_compatible_range<value_type> _Rg, | |
| __allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(from_range_t, _Rg&& __rg, | |
| const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__comp, __a) | |
| { insert_range(std::forward<_Rg>(__rg)); } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(initializer_list<value_type> __il, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__il, key_compare(), __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(initializer_list<value_type> __il, | |
| const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__il.begin(), __il.end(), __comp, __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| initializer_list<value_type> __il, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__s, __il.begin(), __il.end(), key_compare(), __a) | |
| { } | |
| template<__allocator_for<container_type> _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(__sorted_t __s, | |
| initializer_list<value_type> __il, | |
| const key_compare& __comp, | |
| const _Alloc& __a) | |
| : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp, __a) | |
| { } | |
| _Flat_set_impl(const _Flat_set_impl&) = default; | |
| _Flat_set_impl& operator=(const _Flat_set_impl&) = default; | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl(_Flat_set_impl&& __other) | |
| noexcept(is_nothrow_move_constructible_v<container_type> | |
| && is_nothrow_move_constructible_v<key_compare>) | |
| #if __cpp_exceptions | |
| try | |
| #endif | |
| : _M_cont(std::move(__other._M_cont)), _M_comp(std::move(__other._M_comp)) | |
| { __other.clear(); } | |
| #if __cpp_exceptions | |
| catch (...) | |
| { __other.clear(); } | |
| #endif | |
| _GLIBCXX26_CONSTEXPR | |
| _Flat_set_impl& | |
| operator=(_Flat_set_impl&& __other) | |
| noexcept(is_nothrow_move_assignable_v<container_type> | |
| && is_nothrow_move_assignable_v<key_compare>) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| auto __guard_other = _ClearGuard{__other._M_cont}; | |
| _M_cont = std::move(__other._M_cont); | |
| _M_comp = std::move(__other._M_comp); | |
| __guard._M_disable(); | |
| // __guard_other._M_disable is deliberately not called. | |
| return *this; | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| _Derived& | |
| operator=(initializer_list<value_type> __il) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| _M_cont = __il; | |
| _M_sort_uniq(); | |
| __guard._M_disable(); | |
| return static_cast<_Derived&>(*this); | |
| } | |
| // iterators | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| begin() const noexcept | |
| { return _M_cont.begin(); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| end() const noexcept | |
| { return _M_cont.end(); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_reverse_iterator | |
| rbegin() const noexcept | |
| { return const_reverse_iterator(end()); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_reverse_iterator | |
| rend() const noexcept | |
| { return const_reverse_iterator(begin()); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| cbegin() const noexcept | |
| { return begin(); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| cend() const noexcept | |
| { return end(); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_reverse_iterator | |
| crbegin() const noexcept | |
| { return rbegin(); } | |
| _GLIBCXX26_CONSTEXPR | |
| const_reverse_iterator | |
| crend() const noexcept | |
| { return rend(); } | |
| // capacity | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| bool | |
| empty() const noexcept | |
| { return _M_cont.empty(); } | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| size() const noexcept | |
| { return _M_cont.size(); } | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| max_size() const noexcept | |
| { return _M_cont.max_size(); } | |
| // modifiers | |
| template<typename _Arg, typename... _Args> | |
| _GLIBCXX26_CONSTEXPR | |
| pair<iterator, bool> | |
| _M_try_emplace(optional<const_iterator> __hint, _Arg&& __arg, _Args&&... __args) | |
| { | |
| // TODO: Simplify and audit the hint handling. | |
| auto&& __k = [&] -> decltype(auto) { | |
| if constexpr (sizeof...(_Args) == 0 | |
| && same_as<remove_cvref_t<_Arg>, value_type>) | |
| return std::forward<_Arg>(__arg); | |
| else | |
| return value_type(std::forward<_Arg>(__arg), | |
| std::forward<_Args>(__args)...); | |
| }(); | |
| typename container_type::iterator __it; | |
| int __r = -1, __s = -1; | |
| if (__hint.has_value() | |
| && (__hint == cbegin() | |
| || (__r = !_M_comp(__k, (*__hint)[-1]))) // k >= hint[-1] | |
| && (__hint == cend() | |
| || (__s = !_M_comp((*__hint)[0], __k)))) // k <= hint[0] | |
| { | |
| __it = _M_cont.begin() + (*__hint - begin()); | |
| if constexpr (!_Multi) | |
| if (__r == 1 && !_M_comp(__it[-1], __k)) // k == hint[-1] | |
| return {__it - 1, false}; | |
| } | |
| else | |
| { | |
| auto __first = _M_cont.begin(); | |
| auto __last = _M_cont.end(); | |
| if (__r == 1) // k >= hint[-1] | |
| __first += *__hint - _M_cont.begin(); | |
| else if (__r == 0) // k < __hint[-1] | |
| __last = __first + (*__hint - _M_cont.begin()); | |
| if constexpr (_Multi) | |
| { | |
| if (__s == 0) // hint[0] < k | |
| // Insert before the leftmost equivalent key. | |
| __it = std::lower_bound(__first, __last, __k, _M_comp); | |
| else | |
| // Insert after the rightmost equivalent key. | |
| __it = std::upper_bound(std::make_reverse_iterator(__last), | |
| std::make_reverse_iterator(__first), | |
| __k, std::not_fn(_M_comp)).base(); | |
| } | |
| else | |
| __it = std::lower_bound(__first, __last, __k, _M_comp); | |
| } | |
| if constexpr (!_Multi) | |
| if (__it != _M_cont.end() && !_M_comp(__k, __it[0])) | |
| return {__it, false}; | |
| auto __guard = _M_make_clear_guard(); | |
| __it = _M_cont.insert(__it, std::forward<decltype(__k)>(__k)); | |
| __guard._M_disable(); | |
| return {__it, true}; | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| pair<iterator, bool> | |
| _M_try_emplace(optional<const_iterator> __hint) | |
| { return _M_try_emplace(__hint, value_type()); } | |
| template<typename... _Args> | |
| requires is_constructible_v<value_type, _Args...> | |
| _GLIBCXX26_CONSTEXPR | |
| __emplace_result_t | |
| emplace(_Args&&... __args) | |
| { | |
| auto __r = _M_try_emplace(nullopt, std::forward<_Args>(__args)...); | |
| if constexpr (_Multi) | |
| return __r.first; | |
| else | |
| return __r; | |
| } | |
| template<typename... _Args> | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| emplace_hint(const_iterator __position, _Args&&... __args) | |
| { return _M_try_emplace(__position, std::forward<_Args>(__args)...).first; } | |
| _GLIBCXX26_CONSTEXPR | |
| __emplace_result_t | |
| insert(const value_type& __x) | |
| { return emplace(__x); } | |
| _GLIBCXX26_CONSTEXPR | |
| __emplace_result_t | |
| insert(value_type&& __x) | |
| { return emplace(std::move(__x)); } | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| insert(const_iterator __position, const value_type& __x) | |
| { return emplace_hint(__position, __x); } | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| insert(const_iterator __position, value_type&& __x) | |
| { return emplace_hint(__position, std::move(__x)); } | |
| template<typename _Arg> | |
| requires is_constructible_v<value_type, _Arg> | |
| _GLIBCXX26_CONSTEXPR | |
| __emplace_result_t | |
| insert(_Arg&& __x) | |
| { return emplace(std::forward<_Arg>(__x)); } | |
| template<typename _Arg> | |
| requires is_constructible_v<value_type, _Arg> | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| insert(const_iterator __position, _Arg&& __x) | |
| { return emplace_hint(__position, std::forward<_Arg>(__x)); } | |
| template<__has_input_iter_cat _InputIterator> | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert(_InputIterator __first, _InputIterator __last) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| auto __it = _M_cont.insert(_M_cont.end(), __first, __last); | |
| std::sort(__it, _M_cont.end(), _M_comp); | |
| std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp); | |
| if constexpr (!_Multi) | |
| _M_unique(); | |
| __guard._M_disable(); | |
| } | |
| template<__has_input_iter_cat _InputIterator> | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert(__sorted_t, _InputIterator __first, _InputIterator __last) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| auto __it = _M_cont.insert(_M_cont.end(), __first, __last); | |
| std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp); | |
| if constexpr (!_Multi) | |
| _M_unique(); | |
| __guard._M_disable(); | |
| } | |
| template<typename _Rg> | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| _M_insert_range(_Rg&& __rg, bool __is_sorted = false) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| typename container_type::iterator __it; | |
| if constexpr (requires { _M_cont.insert_range(_M_cont.end(), __rg); }) | |
| __it = _M_cont.insert_range(_M_cont.end(), __rg); | |
| else if constexpr (ranges::common_range<_Rg> | |
| && __has_input_iter_cat<ranges::iterator_t<_Rg>>) | |
| __it = _M_cont.insert(_M_cont.end(), ranges::begin(__rg), ranges::end(__rg)); | |
| else | |
| { | |
| size_type __n = size(); | |
| auto __first = ranges::begin(__rg); | |
| auto __last = ranges::end(__rg); | |
| for (; __first != __last; ++__first) | |
| _M_cont.emplace_back(*__first); | |
| __it = _M_cont.begin() + __n; | |
| } | |
| if (__is_sorted) | |
| _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(__it, _M_cont.end(), _M_comp)); | |
| else | |
| std::sort(__it, _M_cont.end(), _M_comp); | |
| std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp); | |
| if constexpr (!_Multi) | |
| _M_unique(); | |
| __guard._M_disable(); | |
| } | |
| template<__detail::__container_compatible_range<value_type> _Rg> | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert_range(_Rg&& __rg) | |
| { _M_insert_range(std::forward<_Rg>(__rg)); } | |
| template<__detail::__container_compatible_range<value_type> _Rg> | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert_range(__sorted_t, _Rg&& __rg) | |
| { _M_insert_range(std::forward<_Rg>(__rg), true); } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert(initializer_list<value_type> __il) | |
| { insert(__il.begin(), __il.end()); } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| insert(__sorted_t __s, initializer_list<value_type> __il) | |
| { insert(__s, __il.begin(), __il.end()); } | |
| _GLIBCXX26_CONSTEXPR | |
| container_type | |
| extract() && | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| return std::move(_M_cont); | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| replace(container_type&& __cont) | |
| { | |
| _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(__cont, _M_comp)); | |
| auto __guard = _M_make_clear_guard(); | |
| _M_cont = std::move(__cont); | |
| __guard._M_disable(); | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| erase(const_iterator __position) | |
| { return _M_cont.erase(__position); } | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| erase(const key_type& __x) | |
| { return erase<const key_type&>(__x); } | |
| template<typename _Key2> | |
| requires same_as<remove_cvref_t<_Key2>, _Key> | |
| || (__transparent_comparator<_Compare> | |
| && !is_convertible_v<_Key2, iterator> | |
| && !is_convertible_v<_Key2, const_iterator>) | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| erase(_Key2&& __x) | |
| { | |
| auto [__first, __last] = equal_range(std::forward<_Key2>(__x)); | |
| auto __n = __last - __first; | |
| erase(__first, __last); | |
| return __n; | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| erase(const_iterator __first, const_iterator __last) | |
| { return _M_cont.erase(__first, __last); } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| swap(_Derived& __y) | |
| noexcept(is_nothrow_swappable_v<container_type> | |
| && is_nothrow_swappable_v<key_compare>) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| auto __guard_y = _ClearGuard{__y._M_cont}; | |
| ranges::swap(_M_cont, __y._M_cont); | |
| ranges::swap(_M_comp, __y._M_comp); | |
| __guard._M_disable(); | |
| __guard_y._M_disable(); | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| clear() noexcept | |
| { _M_cont.clear(); } | |
| // observers | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| key_compare | |
| key_comp() const | |
| { return _M_comp; } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| value_compare | |
| value_comp() const | |
| { return _M_comp; } | |
| // set operations | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| find(const key_type& __x) | |
| { return find<key_type>(__x); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| find(const key_type& __x) const | |
| { return find<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| find(const _Key2& __x) | |
| { | |
| auto __it = lower_bound(__x); | |
| if (__it != end() && !_M_comp(__x, *__it)) | |
| return __it; | |
| else | |
| return end(); | |
| } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| find(const _Key2& __x) const | |
| { | |
| auto __it = lower_bound(__x); | |
| if (__it != cend() && !_M_comp(__x, *__it)) | |
| return __it; | |
| else | |
| return cend(); | |
| } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| count(const key_type& __x) const | |
| { return count<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| count(const _Key2& __x) const | |
| { | |
| if constexpr (!_Multi) | |
| return contains<_Key2>(__x); | |
| else | |
| { | |
| auto [__first, __last] = equal_range(__x); | |
| return __last - __first; | |
| } | |
| } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| bool | |
| contains(const key_type& __x) const | |
| { return contains<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| bool | |
| contains(const _Key2& __x) const | |
| { return find(__x) != cend(); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| lower_bound(const key_type& __x) | |
| { return lower_bound<key_type>(__x); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| lower_bound(const key_type& __x) const | |
| { return lower_bound<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| lower_bound(const _Key2& __x) | |
| { return std::lower_bound(begin(), end(), __x, _M_comp); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| lower_bound(const _Key2& __x) const | |
| { return std::lower_bound(begin(), end(), __x, _M_comp); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| upper_bound(const key_type& __x) | |
| { return upper_bound<key_type>(__x); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| upper_bound(const key_type& __x) const | |
| { return upper_bound<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| iterator | |
| upper_bound(const _Key2& __x) | |
| { return std::upper_bound(begin(), end(), __x, _M_comp); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| const_iterator | |
| upper_bound(const _Key2& __x) const | |
| { return std::upper_bound(begin(), end(), __x, _M_comp); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| pair<iterator, iterator> | |
| equal_range(const key_type& __x) | |
| { return equal_range<key_type>(__x); } | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| pair<const_iterator, const_iterator> | |
| equal_range(const key_type& __x) const | |
| { return equal_range<key_type>(__x); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| pair<iterator, iterator> | |
| equal_range(const _Key2& __x) | |
| { return std::equal_range(begin(), end(), __x, _M_comp); } | |
| template<typename _Key2> | |
| requires same_as<_Key2, _Key> || __transparent_comparator<_Compare> | |
| [[nodiscard]] | |
| _GLIBCXX26_CONSTEXPR | |
| pair<const_iterator, const_iterator> | |
| equal_range(const _Key2& __x) const | |
| { return std::equal_range(begin(), end(), __x, _M_comp); } | |
| [[nodiscard]] | |
| friend _GLIBCXX26_CONSTEXPR bool | |
| operator==(const _Derived& __x, const _Derived& __y) | |
| { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); } | |
| template<typename _Up = value_type> | |
| [[nodiscard]] | |
| friend _GLIBCXX26_CONSTEXPR __detail::__synth3way_t<_Up> | |
| operator<=>(const _Derived& __x, const _Derived& __y) | |
| { | |
| return std::lexicographical_compare_three_way(__x.begin(), __x.end(), | |
| __y.begin(), __y.end(), | |
| __detail::__synth3way); | |
| } | |
| friend _GLIBCXX26_CONSTEXPR void | |
| swap(_Derived& __x, _Derived& __y) noexcept(noexcept(__x.swap(__y))) | |
| { return __x.swap(__y); } | |
| template<typename _Predicate> | |
| _GLIBCXX26_CONSTEXPR | |
| size_type | |
| _M_erase_if(_Predicate __pred) | |
| { | |
| auto __guard = _M_make_clear_guard(); | |
| auto __first = _M_cont.begin(); | |
| auto __last = _M_cont.end(); | |
| __first = std::remove_if(__first, __last, __pred); | |
| auto __n = __last - __first; | |
| erase(__first, __last); | |
| __guard._M_disable(); | |
| return __n; | |
| } | |
| private: | |
| container_type _M_cont; | |
| [[no_unique_address]] _Compare _M_comp; | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| _M_sort_uniq() | |
| { | |
| std::sort(_M_cont.begin(), _M_cont.end(), _M_comp); | |
| if constexpr (!_Multi) | |
| _M_unique(); | |
| } | |
| _GLIBCXX26_CONSTEXPR | |
| void | |
| _M_unique() requires (!_Multi) | |
| { | |
| struct __key_equiv | |
| { | |
| _GLIBCXX26_CONSTEXPR | |
| __key_equiv(key_compare __c) : _M_comp(__c) { } | |
| _GLIBCXX26_CONSTEXPR | |
| bool | |
| operator()(const_reference __x, const_reference __y) const | |
| { return !_M_comp(__x, __y) && !_M_comp(__y, __x); } | |
| [[no_unique_address]] key_compare _M_comp; | |
| }; | |
| auto __first = _M_cont.begin(); | |
| auto __last = _M_cont.end(); | |
| __first = std::unique(__first, __last, __key_equiv(_M_comp)); | |
| _M_cont.erase(__first, __last); | |
| } | |
| }; | |
| /* Class template flat_set - container adaptor | |
| * | |
| * @ingroup | |
| */ | |
| template<typename _Key, typename _Compare = less<_Key>, | |
| typename _KeyContainer = vector<_Key>> | |
| class flat_set | |
| : private _Flat_set_impl<_Key, _Compare, _KeyContainer, false> | |
| { | |
| using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, false>; | |
| friend _Impl; | |
| public: | |
| // types | |
| using typename _Impl::key_type; | |
| using typename _Impl::value_type; | |
| using typename _Impl::key_compare; | |
| using typename _Impl::reference; | |
| using typename _Impl::const_reference; | |
| using typename _Impl::size_type; | |
| using typename _Impl::difference_type; | |
| using typename _Impl::iterator; | |
| using typename _Impl::const_iterator; | |
| using typename _Impl::reverse_iterator; | |
| using typename _Impl::const_reverse_iterator; | |
| using typename _Impl::container_type; | |
| using typename _Impl::value_compare; | |
| // constructors | |
| using _Impl::_Impl; | |
| // operator=(initializer_list<value_type>) | |
| // Although this also brings in the base move/copy assignment operators, | |
| // they will be hidden by our synthesized ones. | |
| using _Impl::operator=; | |
| // iterators | |
| using _Impl::begin; | |
| using _Impl::end; | |
| using _Impl::rbegin; | |
| using _Impl::rend; | |
| using _Impl::cbegin; | |
| using _Impl::cend; | |
| using _Impl::crbegin; | |
| using _Impl::crend; | |
| // capacity | |
| using _Impl::empty; | |
| using _Impl::size; | |
| using _Impl::max_size; | |
| // modifiers | |
| using _Impl::emplace; | |
| using _Impl::emplace_hint; | |
| using _Impl::insert; | |
| using _Impl::insert_range; | |
| using _Impl::extract; | |
| using _Impl::replace; | |
| using _Impl::erase; | |
| using _Impl::swap; | |
| using _Impl::clear; | |
| // observers | |
| using _Impl::key_comp; | |
| using _Impl::value_comp; | |
| // set operations | |
| using _Impl::find; | |
| using _Impl::count; | |
| using _Impl::contains; | |
| using _Impl::lower_bound; | |
| using _Impl::upper_bound; | |
| using _Impl::equal_range; | |
| using _Impl::_M_erase_if; | |
| }; | |
| template<typename _KeyContainer, | |
| __not_allocator_like _Compare = less<typename _KeyContainer::value_type>> | |
| flat_set(_KeyContainer, _Compare = _Compare()) | |
| -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc> | |
| flat_set(_KeyContainer, _Alloc) | |
| -> flat_set<typename _KeyContainer::value_type, | |
| less<typename _KeyContainer::value_type>, _KeyContainer>; | |
| template<typename _KeyContainer, __not_allocator_like _Compare, | |
| __allocator_for<_KeyContainer> _Alloc> | |
| flat_set(_KeyContainer, _Compare, _Alloc) | |
| -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, | |
| __not_allocator_like _Compare = less<typename _KeyContainer::value_type>> | |
| flat_set(sorted_unique_t, _KeyContainer, _Compare = _Compare()) | |
| -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc> | |
| flat_set(sorted_unique_t, _KeyContainer, _Alloc) | |
| -> flat_set<typename _KeyContainer::value_type, | |
| less<typename _KeyContainer::value_type>, _KeyContainer>; | |
| template<typename _KeyContainer, __not_allocator_like _Compare, | |
| __allocator_for<_KeyContainer> _Alloc> | |
| flat_set(sorted_unique_t, _KeyContainer, _Compare, _Alloc) | |
| -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<__has_input_iter_cat _InputIterator, | |
| __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>> | |
| flat_set(_InputIterator, _InputIterator, _Compare = _Compare()) | |
| -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>; | |
| template<__has_input_iter_cat _InputIterator, | |
| __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>> | |
| flat_set(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) | |
| -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>; | |
| template<ranges::input_range _Rg, | |
| __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>, | |
| __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>> | |
| flat_set(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc()) | |
| -> flat_set<ranges::range_value_t<_Rg>, _Compare, | |
| vector<ranges::range_value_t<_Rg>, | |
| __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>; | |
| template<ranges::input_range _Rg, __allocator_like _Alloc> | |
| flat_set(from_range_t, _Rg&&, _Alloc) | |
| -> flat_set<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>, | |
| vector<ranges::range_value_t<_Rg>, | |
| __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>; | |
| template<typename _Key, __not_allocator_like _Compare = less<_Key>> | |
| flat_set(initializer_list<_Key>, _Compare = _Compare()) | |
| -> flat_set<_Key, _Compare>; | |
| template<typename _Key, __not_allocator_like _Compare = less<_Key>> | |
| flat_set(sorted_unique_t, initializer_list<_Key>, _Compare = _Compare()) | |
| -> flat_set<_Key, _Compare>; | |
| template<typename _Key, typename _Compare, | |
| typename _KeyContainer, typename _Alloc> | |
| struct uses_allocator<flat_set<_Key, _Compare, _KeyContainer>, _Alloc> | |
| : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>> | |
| { }; | |
| template<typename _Key, typename _Compare, typename _KeyContainer, | |
| typename _Predicate> | |
| _GLIBCXX26_CONSTEXPR | |
| typename flat_set<_Key, _Compare, _KeyContainer>::size_type | |
| erase_if(flat_set<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred) | |
| { return __c._M_erase_if(std::move(__pred)); } | |
| /* Class template flat_multiset - container adaptor | |
| * | |
| * @ingroup | |
| */ | |
| template<typename _Key, typename _Compare = less<_Key>, | |
| typename _KeyContainer = vector<_Key>> | |
| class flat_multiset | |
| : private _Flat_set_impl<_Key, _Compare, _KeyContainer, true> | |
| { | |
| using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, true>; | |
| friend _Impl; | |
| public: | |
| // types | |
| using typename _Impl::key_type; | |
| using typename _Impl::value_type; | |
| using typename _Impl::key_compare; | |
| using typename _Impl::reference; | |
| using typename _Impl::const_reference; | |
| using typename _Impl::size_type; | |
| using typename _Impl::difference_type; | |
| using typename _Impl::iterator; | |
| using typename _Impl::const_iterator; | |
| using typename _Impl::reverse_iterator; | |
| using typename _Impl::const_reverse_iterator; | |
| using typename _Impl::container_type; | |
| using typename _Impl::value_compare; | |
| // constructors | |
| using _Impl::_Impl; | |
| // operator=(initializer_list<value_type>) | |
| // Although this also brings in the base move/copy assignment operators, | |
| // they will be hidden by our synthesized ones. | |
| using _Impl::operator=; | |
| // iterators | |
| using _Impl::begin; | |
| using _Impl::end; | |
| using _Impl::rbegin; | |
| using _Impl::rend; | |
| using _Impl::cbegin; | |
| using _Impl::cend; | |
| using _Impl::crbegin; | |
| using _Impl::crend; | |
| // capacity | |
| using _Impl::empty; | |
| using _Impl::size; | |
| using _Impl::max_size; | |
| // modifiers | |
| using _Impl::emplace; | |
| using _Impl::emplace_hint; | |
| using _Impl::insert; | |
| using _Impl::insert_range; | |
| using _Impl::extract; | |
| using _Impl::replace; | |
| using _Impl::erase; | |
| using _Impl::swap; | |
| using _Impl::clear; | |
| // observers | |
| using _Impl::key_comp; | |
| using _Impl::value_comp; | |
| // set operations | |
| using _Impl::find; | |
| using _Impl::count; | |
| using _Impl::contains; | |
| using _Impl::lower_bound; | |
| using _Impl::upper_bound; | |
| using _Impl::equal_range; | |
| using _Impl::_M_erase_if; | |
| }; | |
| template<typename _KeyContainer, | |
| __not_allocator_like _Compare = less<typename _KeyContainer::value_type>> | |
| flat_multiset(_KeyContainer, _Compare = _Compare()) | |
| -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc> | |
| flat_multiset(_KeyContainer, _Alloc) | |
| -> flat_multiset<typename _KeyContainer::value_type, | |
| less<typename _KeyContainer::value_type>, _KeyContainer>; | |
| template<typename _KeyContainer, __not_allocator_like _Compare, | |
| __allocator_for<_KeyContainer> _Alloc> | |
| flat_multiset(_KeyContainer, _Compare, _Alloc) | |
| -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, | |
| __not_allocator_like _Compare = less<typename _KeyContainer::value_type>> | |
| flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare()) | |
| -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc> | |
| flat_multiset(sorted_equivalent_t, _KeyContainer, _Alloc) | |
| -> flat_multiset<typename _KeyContainer::value_type, | |
| less<typename _KeyContainer::value_type>, _KeyContainer>; | |
| template<typename _KeyContainer, __not_allocator_like _Compare, | |
| __allocator_for<_KeyContainer> _Alloc> | |
| flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Alloc) | |
| -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>; | |
| template<__has_input_iter_cat _InputIterator, | |
| __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>> | |
| flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare()) | |
| -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>; | |
| template<__has_input_iter_cat _InputIterator, | |
| __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>> | |
| flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare()) | |
| -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>; | |
| template<ranges::input_range _Rg, | |
| __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>, | |
| __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>> | |
| flat_multiset(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc()) | |
| -> flat_multiset<ranges::range_value_t<_Rg>, _Compare, | |
| vector<ranges::range_value_t<_Rg>, | |
| __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>; | |
| template<ranges::input_range _Rg, __allocator_like _Alloc> | |
| flat_multiset(from_range_t, _Rg&&, _Alloc) | |
| -> flat_multiset<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>, | |
| vector<ranges::range_value_t<_Rg>, | |
| __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>; | |
| template<typename _Key, __not_allocator_like _Compare = less<_Key>> | |
| flat_multiset(initializer_list<_Key>, _Compare = _Compare()) | |
| -> flat_multiset<_Key, _Compare>; | |
| template<typename _Key, __not_allocator_like _Compare = less<_Key>> | |
| flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) | |
| -> flat_multiset<_Key, _Compare>; | |
| template<typename _Key, typename _Compare, | |
| typename _KeyContainer, typename _Alloc> | |
| struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Alloc> | |
| : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>> | |
| { }; | |
| template<typename _Key, typename _Compare, typename _KeyContainer, | |
| typename _Predicate> | |
| _GLIBCXX26_CONSTEXPR | |
| typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type | |
| erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred) | |
| { return __c._M_erase_if(std::move(__pred)); } | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std | |
| #endif // __cpp_lib_flat_set | |
| #endif // _GLIBCXX_FLAT_SET |