1 // <flat_set> -*- C++ -*-
3 // Copyright The GNU Toolchain Authors.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/flat_set
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_FLAT_SET
30 #define _GLIBCXX_FLAT_SET 1
32 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
36 #define __glibcxx_want_constexpr_flat_set
37 #define __glibcxx_want_flat_set
38 #include <bits/version.h>
40 #ifdef __cpp_lib_flat_set // >= C++23
43 #include <initializer_list>
46 #include <functional> // not_fn
48 #include <type_traits>
50 #include <bits/stl_algo.h>
51 #include <bits/stl_function.h> // less
52 #include <bits/stl_pair.h>
53 #include <bits/uses_allocator_args.h> // make_obj_using_allocator
55 # include <bits/ranges_algo.h> // ranges::is_sorted
58 namespace std _GLIBCXX_VISIBILITY(default)
60 _GLIBCXX_BEGIN_NAMESPACE_VERSION
62 template<typename _Key, typename _Compare,
63 typename _KeyContainer>
66 template<typename _Key, typename _Compare,
67 typename _KeyContainer>
70 template<typename _Key, typename _Compare, typename _KeyContainer, bool _Multi>
73 static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
75 using _Derived = __conditional_t<_Multi,
76 flat_multiset<_Key, _Compare, _KeyContainer>,
77 flat_set<_Key, _Compare, _KeyContainer>>;
78 using __sorted_t = __conditional_t<_Multi, sorted_equivalent_t, sorted_unique_t>;
81 using key_type = _Key;
82 using value_type = _Key;
83 using key_compare = _Compare;
84 using value_compare = _Compare;
85 using reference = value_type&;
86 using const_reference = const value_type&;
87 using size_type = typename _KeyContainer::size_type;
88 using difference_type = typename _KeyContainer::difference_type;
89 using iterator = typename _KeyContainer::const_iterator;
90 using const_iterator = typename _KeyContainer::const_iterator;
91 using reverse_iterator = std::reverse_iterator<iterator>;
92 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
93 using container_type = _KeyContainer;
96 using __emplace_result_t = __conditional_t<_Multi, iterator, pair<iterator, bool>>;
100 container_type* _M_cont;
103 _ClearGuard(container_type& __cont)
104 : _M_cont(std::__addressof(__cont))
117 { _M_cont = nullptr; }
122 _M_make_clear_guard()
123 { return _ClearGuard{this->_M_cont}; }
128 _Flat_set_impl() : _Flat_set_impl(key_compare()) { }
132 _Flat_set_impl(const key_compare& __comp)
133 : _M_cont(), _M_comp(__comp)
137 _Flat_set_impl(container_type __cont, const key_compare& __comp = key_compare())
138 : _M_cont(std::move(__cont)), _M_comp(__comp)
142 _Flat_set_impl(__sorted_t,
143 container_type __cont, const key_compare& __comp = key_compare())
144 : _M_cont(std::move(__cont)), _M_comp(__comp)
145 { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }
147 template<__has_input_iter_cat _InputIterator>
149 _Flat_set_impl(_InputIterator __first, _InputIterator __last,
150 const key_compare& __comp = key_compare())
151 : _M_cont(), _M_comp(__comp)
152 { insert(__first, __last); }
154 template<__has_input_iter_cat _InputIterator>
156 _Flat_set_impl(__sorted_t __s,
157 _InputIterator __first, _InputIterator __last,
158 const key_compare& __comp = key_compare())
159 : _M_cont(), _M_comp(__comp)
160 { insert(__s, __first, __last); }
162 template<__detail::__container_compatible_range<value_type> _Rg>
164 _Flat_set_impl(from_range_t, _Rg&& __rg)
165 : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), key_compare())
168 template<__detail::__container_compatible_range<value_type> _Rg>
170 _Flat_set_impl(from_range_t, _Rg&& __rg, const key_compare& __comp)
171 : _Flat_set_impl(__comp)
172 { insert_range(std::forward<_Rg>(__rg)); }
175 _Flat_set_impl(initializer_list<value_type> __il,
176 const key_compare& __comp = key_compare())
177 : _Flat_set_impl(__il.begin(), __il.end(), __comp)
181 _Flat_set_impl(__sorted_t __s,
182 initializer_list<value_type> __il,
183 const key_compare& __comp = key_compare())
184 : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp)
187 // constructors with allocators
189 template<__allocator_for<container_type> _Alloc>
192 _Flat_set_impl(const _Alloc& __a)
193 : _Flat_set_impl(key_compare(), __a)
196 template<__allocator_for<container_type> _Alloc>
198 _Flat_set_impl(const key_compare& __comp, const _Alloc& __a)
199 : _M_cont(std::make_obj_using_allocator<container_type>(__a)),
203 template<__allocator_for<container_type> _Alloc>
205 _Flat_set_impl(const container_type& __cont, const _Alloc& __a)
206 : _Flat_set_impl(__cont, key_compare(), __a)
209 template<__allocator_for<container_type> _Alloc>
211 _Flat_set_impl(const container_type& __cont, const key_compare& __comp,
213 : _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)),
217 template<__allocator_for<container_type> _Alloc>
219 _Flat_set_impl(__sorted_t __s, const container_type& __cont, const _Alloc& __a)
220 : _Flat_set_impl(__s, __cont, key_compare(), __a)
223 template<__allocator_for<container_type> _Alloc>
225 _Flat_set_impl(__sorted_t, const container_type& __cont, const key_compare& __comp,
227 : _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)),
229 { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }
231 template<__allocator_for<container_type> _Alloc>
233 _Flat_set_impl(const _Derived& __x, const _Alloc& __a)
234 : _M_cont(std::make_obj_using_allocator<container_type>(__a, __x._M_cont)),
238 template<__allocator_for<container_type> _Alloc>
240 _Flat_set_impl(_Derived&& __x, const _Alloc& __a)
241 : _M_cont(std::make_obj_using_allocator<container_type>(__a, std::move(__x._M_cont))),
245 template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>
247 _Flat_set_impl(_InputIterator __first, _InputIterator __last,
249 : _Flat_set_impl(std::move(__first), std::move(__last), key_compare(), __a)
252 template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>
254 _Flat_set_impl(_InputIterator __first, _InputIterator __last,
255 const key_compare& __comp,
257 : _Flat_set_impl(__comp, __a)
258 { insert(__first, __last); }
260 template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>
262 _Flat_set_impl(__sorted_t __s,
263 _InputIterator __first, _InputIterator __last,
265 : _Flat_set_impl(__s, std::move(__first), std::move(__last), key_compare(), __a)
268 template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>
270 _Flat_set_impl(__sorted_t __s,
271 _InputIterator __first, _InputIterator __last,
272 const key_compare& __comp,
274 : _Flat_set_impl(__comp, __a)
275 { insert(__s, __first, __last); }
277 template<__detail::__container_compatible_range<value_type> _Rg,
278 __allocator_for<container_type> _Alloc>
280 _Flat_set_impl(from_range_t, _Rg&& __rg,
282 : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), key_compare(), __a)
285 template<__detail::__container_compatible_range<value_type> _Rg,
286 __allocator_for<container_type> _Alloc>
288 _Flat_set_impl(from_range_t, _Rg&& __rg,
289 const key_compare& __comp,
291 : _Flat_set_impl(__comp, __a)
292 { insert_range(std::forward<_Rg>(__rg)); }
294 template<__allocator_for<container_type> _Alloc>
296 _Flat_set_impl(initializer_list<value_type> __il,
298 : _Flat_set_impl(__il, key_compare(), __a)
301 template<__allocator_for<container_type> _Alloc>
303 _Flat_set_impl(initializer_list<value_type> __il,
304 const key_compare& __comp,
306 : _Flat_set_impl(__il.begin(), __il.end(), __comp, __a)
309 template<__allocator_for<container_type> _Alloc>
311 _Flat_set_impl(__sorted_t __s,
312 initializer_list<value_type> __il,
314 : _Flat_set_impl(__s, __il.begin(), __il.end(), key_compare(), __a)
317 template<__allocator_for<container_type> _Alloc>
319 _Flat_set_impl(__sorted_t __s,
320 initializer_list<value_type> __il,
321 const key_compare& __comp,
323 : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp, __a)
326 _Flat_set_impl(const _Flat_set_impl&) = default;
327 _Flat_set_impl& operator=(const _Flat_set_impl&) = default;
330 _Flat_set_impl(_Flat_set_impl&& __other)
331 noexcept(is_nothrow_move_constructible_v<container_type>
332 && is_nothrow_move_constructible_v<key_compare>)
336 : _M_cont(std::move(__other._M_cont)), _M_comp(std::move(__other._M_comp))
345 operator=(_Flat_set_impl&& __other)
346 noexcept(is_nothrow_move_assignable_v<container_type>
347 && is_nothrow_move_assignable_v<key_compare>)
349 auto __guard = _M_make_clear_guard();
350 auto __guard_other = _ClearGuard{__other._M_cont};
351 _M_cont = std::move(__other._M_cont);
352 _M_comp = std::move(__other._M_comp);
353 __guard._M_disable();
354 // __guard_other._M_disable is deliberately not called.
360 operator=(initializer_list<value_type> __il)
362 auto __guard = _M_make_clear_guard();
365 __guard._M_disable();
366 return static_cast<_Derived&>(*this);
372 begin() const noexcept
373 { return _M_cont.begin(); }
378 { return _M_cont.end(); }
381 const_reverse_iterator
382 rbegin() const noexcept
383 { return const_reverse_iterator(end()); }
386 const_reverse_iterator
387 rend() const noexcept
388 { return const_reverse_iterator(begin()); }
392 cbegin() const noexcept
397 cend() const noexcept
401 const_reverse_iterator
402 crbegin() const noexcept
406 const_reverse_iterator
407 crend() const noexcept
414 empty() const noexcept
415 { return _M_cont.empty(); }
419 size() const noexcept
420 { return _M_cont.size(); }
424 max_size() const noexcept
425 { return _M_cont.max_size(); }
428 template<typename _Arg, typename... _Args>
431 _M_try_emplace(optional<const_iterator> __hint, _Arg&& __arg, _Args&&... __args)
433 // TODO: Simplify and audit the hint handling.
434 auto&& __k = [&] -> decltype(auto) {
435 if constexpr (sizeof...(_Args) == 0
436 && same_as<remove_cvref_t<_Arg>, value_type>)
437 return std::forward<_Arg>(__arg);
439 return value_type(std::forward<_Arg>(__arg),
440 std::forward<_Args>(__args)...);
442 typename container_type::iterator __it;
443 int __r = -1, __s = -1;
444 if (__hint.has_value()
445 && (__hint == cbegin()
446 || (__r = !_M_comp(__k, (*__hint)[-1]))) // k >= hint[-1]
448 || (__s = !_M_comp((*__hint)[0], __k)))) // k <= hint[0]
450 __it = _M_cont.begin() + (*__hint - begin());
451 if constexpr (!_Multi)
452 if (__r == 1 && !_M_comp(__it[-1], __k)) // k == hint[-1]
453 return {__it - 1, false};
457 auto __first = _M_cont.begin();
458 auto __last = _M_cont.end();
459 if (__r == 1) // k >= hint[-1]
460 __first += *__hint - _M_cont.begin();
461 else if (__r == 0) // k < __hint[-1]
462 __last = __first + (*__hint - _M_cont.begin());
463 if constexpr (_Multi)
465 if (__s == 0) // hint[0] < k
466 // Insert before the leftmost equivalent key.
467 __it = std::lower_bound(__first, __last, __k, _M_comp);
469 // Insert after the rightmost equivalent key.
470 __it = std::upper_bound(std::make_reverse_iterator(__last),
471 std::make_reverse_iterator(__first),
472 __k, std::not_fn(_M_comp)).base();
475 __it = std::lower_bound(__first, __last, __k, _M_comp);
478 if constexpr (!_Multi)
479 if (__it != _M_cont.end() && !_M_comp(__k, __it[0]))
480 return {__it, false};
482 auto __guard = _M_make_clear_guard();
483 __it = _M_cont.insert(__it, std::forward<decltype(__k)>(__k));
484 __guard._M_disable();
488 template<typename... _Args>
491 _M_try_emplace(optional<const_iterator> __hint)
492 { return _M_try_emplace(__hint, value_type()); }
494 template<typename... _Args>
495 requires is_constructible_v<value_type, _Args...>
498 emplace(_Args&&... __args)
500 auto __r = _M_try_emplace(nullopt, std::forward<_Args>(__args)...);
501 if constexpr (_Multi)
507 template<typename... _Args>
510 emplace_hint(const_iterator __position, _Args&&... __args)
511 { return _M_try_emplace(__position, std::forward<_Args>(__args)...).first; }
515 insert(const value_type& __x)
516 { return emplace(__x); }
520 insert(value_type&& __x)
521 { return emplace(std::move(__x)); }
525 insert(const_iterator __position, const value_type& __x)
526 { return emplace_hint(__position, __x); }
530 insert(const_iterator __position, value_type&& __x)
531 { return emplace_hint(__position, std::move(__x)); }
533 template<typename _Arg>
534 requires is_constructible_v<value_type, _Arg>
538 { return emplace(std::forward<_Arg>(__x)); }
540 template<typename _Arg>
541 requires is_constructible_v<value_type, _Arg>
544 insert(const_iterator __position, _Arg&& __x)
545 { return emplace_hint(__position, std::forward<_Arg>(__x)); }
547 template<__has_input_iter_cat _InputIterator>
550 insert(_InputIterator __first, _InputIterator __last)
552 auto __guard = _M_make_clear_guard();
553 auto __it = _M_cont.insert(_M_cont.end(), __first, __last);
554 std::sort(__it, _M_cont.end(), _M_comp);
555 std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp);
556 if constexpr (!_Multi)
558 __guard._M_disable();
561 template<__has_input_iter_cat _InputIterator>
564 insert(__sorted_t, _InputIterator __first, _InputIterator __last)
566 auto __guard = _M_make_clear_guard();
567 auto __it = _M_cont.insert(_M_cont.end(), __first, __last);
568 std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp);
569 if constexpr (!_Multi)
571 __guard._M_disable();
574 template<typename _Rg>
577 _M_insert_range(_Rg&& __rg, bool __is_sorted = false)
579 auto __guard = _M_make_clear_guard();
580 typename container_type::iterator __it;
581 if constexpr (requires { _M_cont.insert_range(_M_cont.end(), __rg); })
582 __it = _M_cont.insert_range(_M_cont.end(), __rg);
583 else if constexpr (ranges::common_range<_Rg>
584 && __has_input_iter_cat<ranges::iterator_t<_Rg>>)
585 __it = _M_cont.insert(_M_cont.end(), ranges::begin(__rg), ranges::end(__rg));
588 size_type __n = size();
589 auto __first = ranges::begin(__rg);
590 auto __last = ranges::end(__rg);
591 for (; __first != __last; ++__first)
592 _M_cont.emplace_back(*__first);
593 __it = _M_cont.begin() + __n;
596 _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(__it, _M_cont.end(), _M_comp));
598 std::sort(__it, _M_cont.end(), _M_comp);
599 std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp);
600 if constexpr (!_Multi)
602 __guard._M_disable();
605 template<__detail::__container_compatible_range<value_type> _Rg>
608 insert_range(_Rg&& __rg)
609 { _M_insert_range(std::forward<_Rg>(__rg)); }
611 template<__detail::__container_compatible_range<value_type> _Rg>
614 insert_range(__sorted_t, _Rg&& __rg)
615 { _M_insert_range(std::forward<_Rg>(__rg), true); }
619 insert(initializer_list<value_type> __il)
620 { insert(__il.begin(), __il.end()); }
624 insert(__sorted_t __s, initializer_list<value_type> __il)
625 { insert(__s, __il.begin(), __il.end()); }
631 auto __guard = _M_make_clear_guard();
632 return std::move(_M_cont);
637 replace(container_type&& __cont)
639 _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(__cont, _M_comp));
640 auto __guard = _M_make_clear_guard();
641 _M_cont = std::move(__cont);
642 __guard._M_disable();
647 erase(const_iterator __position)
648 { return _M_cont.erase(__position); }
652 erase(const key_type& __x)
653 { return erase<const key_type&>(__x); }
655 template<typename _Key2>
656 requires same_as<remove_cvref_t<_Key2>, _Key>
657 || (__transparent_comparator<_Compare>
658 && !is_convertible_v<_Key2, iterator>
659 && !is_convertible_v<_Key2, const_iterator>)
664 auto [__first, __last] = equal_range(std::forward<_Key2>(__x));
665 auto __n = __last - __first;
666 erase(__first, __last);
672 erase(const_iterator __first, const_iterator __last)
673 { return _M_cont.erase(__first, __last); }
678 noexcept(is_nothrow_swappable_v<container_type>
679 && is_nothrow_swappable_v<key_compare>)
681 auto __guard = _M_make_clear_guard();
682 auto __guard_y = _ClearGuard{__y._M_cont};
683 ranges::swap(_M_cont, __y._M_cont);
684 ranges::swap(_M_comp, __y._M_comp);
685 __guard._M_disable();
686 __guard_y._M_disable();
711 find(const key_type& __x)
712 { return find<key_type>(__x); }
717 find(const key_type& __x) const
718 { return find<key_type>(__x); }
720 template<typename _Key2>
721 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
725 find(const _Key2& __x)
727 auto __it = lower_bound(__x);
728 if (__it != end() && !_M_comp(__x, *__it))
734 template<typename _Key2>
735 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
739 find(const _Key2& __x) const
741 auto __it = lower_bound(__x);
742 if (__it != cend() && !_M_comp(__x, *__it))
751 count(const key_type& __x) const
752 { return count<key_type>(__x); }
754 template<typename _Key2>
755 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
759 count(const _Key2& __x) const
761 if constexpr (!_Multi)
762 return contains<_Key2>(__x);
765 auto [__first, __last] = equal_range(__x);
766 return __last - __first;
773 contains(const key_type& __x) const
774 { return contains<key_type>(__x); }
776 template<typename _Key2>
777 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
781 contains(const _Key2& __x) const
782 { return find(__x) != cend(); }
787 lower_bound(const key_type& __x)
788 { return lower_bound<key_type>(__x); }
793 lower_bound(const key_type& __x) const
794 { return lower_bound<key_type>(__x); }
796 template<typename _Key2>
797 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
801 lower_bound(const _Key2& __x)
802 { return std::lower_bound(begin(), end(), __x, _M_comp); }
804 template<typename _Key2>
805 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
809 lower_bound(const _Key2& __x) const
810 { return std::lower_bound(begin(), end(), __x, _M_comp); }
815 upper_bound(const key_type& __x)
816 { return upper_bound<key_type>(__x); }
821 upper_bound(const key_type& __x) const
822 { return upper_bound<key_type>(__x); }
824 template<typename _Key2>
825 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
829 upper_bound(const _Key2& __x)
830 { return std::upper_bound(begin(), end(), __x, _M_comp); }
832 template<typename _Key2>
833 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
837 upper_bound(const _Key2& __x) const
838 { return std::upper_bound(begin(), end(), __x, _M_comp); }
842 pair<iterator, iterator>
843 equal_range(const key_type& __x)
844 { return equal_range<key_type>(__x); }
848 pair<const_iterator, const_iterator>
849 equal_range(const key_type& __x) const
850 { return equal_range<key_type>(__x); }
852 template<typename _Key2>
853 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
856 pair<iterator, iterator>
857 equal_range(const _Key2& __x)
858 { return std::equal_range(begin(), end(), __x, _M_comp); }
860 template<typename _Key2>
861 requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
864 pair<const_iterator, const_iterator>
865 equal_range(const _Key2& __x) const
866 { return std::equal_range(begin(), end(), __x, _M_comp); }
869 friend _GLIBCXX26_CONSTEXPR bool
870 operator==(const _Derived& __x, const _Derived& __y)
871 { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
873 template<typename _Up = value_type>
875 friend _GLIBCXX26_CONSTEXPR __detail::__synth3way_t<_Up>
876 operator<=>(const _Derived& __x, const _Derived& __y)
878 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
879 __y.begin(), __y.end(),
880 __detail::__synth3way);
883 friend _GLIBCXX26_CONSTEXPR void
884 swap(_Derived& __x, _Derived& __y) noexcept(noexcept(__x.swap(__y)))
885 { return __x.swap(__y); }
887 template<typename _Predicate>
890 _M_erase_if(_Predicate __pred)
892 auto __guard = _M_make_clear_guard();
893 auto __first = _M_cont.begin();
894 auto __last = _M_cont.end();
895 __first = std::remove_if(__first, __last, __pred);
896 auto __n = __last - __first;
897 erase(__first, __last);
898 __guard._M_disable();
903 container_type _M_cont;
904 [[no_unique_address]] _Compare _M_comp;
910 std::sort(_M_cont.begin(), _M_cont.end(), _M_comp);
911 if constexpr (!_Multi)
917 _M_unique() requires (!_Multi)
922 __key_equiv(key_compare __c) : _M_comp(__c) { }
926 operator()(const_reference __x, const_reference __y) const
927 { return !_M_comp(__x, __y) && !_M_comp(__y, __x); }
929 [[no_unique_address]] key_compare _M_comp;
932 auto __first = _M_cont.begin();
933 auto __last = _M_cont.end();
934 __first = std::unique(__first, __last, __key_equiv(_M_comp));
935 _M_cont.erase(__first, __last);
939 /* Class template flat_set - container adaptor
943 template<typename _Key, typename _Compare = less<_Key>,
944 typename _KeyContainer = vector<_Key>>
946 : private _Flat_set_impl<_Key, _Compare, _KeyContainer, false>
948 using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, false>;
953 using typename _Impl::key_type;
954 using typename _Impl::value_type;
955 using typename _Impl::key_compare;
956 using typename _Impl::reference;
957 using typename _Impl::const_reference;
958 using typename _Impl::size_type;
959 using typename _Impl::difference_type;
960 using typename _Impl::iterator;
961 using typename _Impl::const_iterator;
962 using typename _Impl::reverse_iterator;
963 using typename _Impl::const_reverse_iterator;
964 using typename _Impl::container_type;
965 using typename _Impl::value_compare;
970 // operator=(initializer_list<value_type>)
971 // Although this also brings in the base move/copy assignment operators,
972 // they will be hidden by our synthesized ones.
973 using _Impl::operator=;
983 using _Impl::crbegin;
989 using _Impl::max_size;
992 using _Impl::emplace;
993 using _Impl::emplace_hint;
995 using _Impl::insert_range;
996 using _Impl::extract;
997 using _Impl::replace;
1003 using _Impl::key_comp;
1004 using _Impl::value_comp;
1009 using _Impl::contains;
1010 using _Impl::lower_bound;
1011 using _Impl::upper_bound;
1012 using _Impl::equal_range;
1014 using _Impl::_M_erase_if;
1017 template<typename _KeyContainer,
1018 __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>
1019 flat_set(_KeyContainer, _Compare = _Compare())
1020 -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1022 template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>
1023 flat_set(_KeyContainer, _Alloc)
1024 -> flat_set<typename _KeyContainer::value_type,
1025 less<typename _KeyContainer::value_type>, _KeyContainer>;
1027 template<typename _KeyContainer, __not_allocator_like _Compare,
1028 __allocator_for<_KeyContainer> _Alloc>
1029 flat_set(_KeyContainer, _Compare, _Alloc)
1030 -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1032 template<typename _KeyContainer,
1033 __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>
1034 flat_set(sorted_unique_t, _KeyContainer, _Compare = _Compare())
1035 -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1037 template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>
1038 flat_set(sorted_unique_t, _KeyContainer, _Alloc)
1039 -> flat_set<typename _KeyContainer::value_type,
1040 less<typename _KeyContainer::value_type>, _KeyContainer>;
1042 template<typename _KeyContainer, __not_allocator_like _Compare,
1043 __allocator_for<_KeyContainer> _Alloc>
1044 flat_set(sorted_unique_t, _KeyContainer, _Compare, _Alloc)
1045 -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1047 template<__has_input_iter_cat _InputIterator,
1048 __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>
1049 flat_set(_InputIterator, _InputIterator, _Compare = _Compare())
1050 -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;
1052 template<__has_input_iter_cat _InputIterator,
1053 __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>
1054 flat_set(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare())
1055 -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;
1057 template<ranges::input_range _Rg,
1058 __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,
1059 __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>>
1060 flat_set(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())
1061 -> flat_set<ranges::range_value_t<_Rg>, _Compare,
1062 vector<ranges::range_value_t<_Rg>,
1063 __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;
1065 template<ranges::input_range _Rg, __allocator_like _Alloc>
1066 flat_set(from_range_t, _Rg&&, _Alloc)
1067 -> flat_set<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>,
1068 vector<ranges::range_value_t<_Rg>,
1069 __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;
1071 template<typename _Key, __not_allocator_like _Compare = less<_Key>>
1072 flat_set(initializer_list<_Key>, _Compare = _Compare())
1073 -> flat_set<_Key, _Compare>;
1075 template<typename _Key, __not_allocator_like _Compare = less<_Key>>
1076 flat_set(sorted_unique_t, initializer_list<_Key>, _Compare = _Compare())
1077 -> flat_set<_Key, _Compare>;
1079 template<typename _Key, typename _Compare,
1080 typename _KeyContainer, typename _Alloc>
1081 struct uses_allocator<flat_set<_Key, _Compare, _KeyContainer>, _Alloc>
1082 : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
1085 template<typename _Key, typename _Compare, typename _KeyContainer,
1086 typename _Predicate>
1087 _GLIBCXX26_CONSTEXPR
1088 typename flat_set<_Key, _Compare, _KeyContainer>::size_type
1089 erase_if(flat_set<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred)
1090 { return __c._M_erase_if(std::move(__pred)); }
1092 /* Class template flat_multiset - container adaptor
1096 template<typename _Key, typename _Compare = less<_Key>,
1097 typename _KeyContainer = vector<_Key>>
1099 : private _Flat_set_impl<_Key, _Compare, _KeyContainer, true>
1101 using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, true>;
1106 using typename _Impl::key_type;
1107 using typename _Impl::value_type;
1108 using typename _Impl::key_compare;
1109 using typename _Impl::reference;
1110 using typename _Impl::const_reference;
1111 using typename _Impl::size_type;
1112 using typename _Impl::difference_type;
1113 using typename _Impl::iterator;
1114 using typename _Impl::const_iterator;
1115 using typename _Impl::reverse_iterator;
1116 using typename _Impl::const_reverse_iterator;
1117 using typename _Impl::container_type;
1118 using typename _Impl::value_compare;
1123 // operator=(initializer_list<value_type>)
1124 // Although this also brings in the base move/copy assignment operators,
1125 // they will be hidden by our synthesized ones.
1126 using _Impl::operator=;
1131 using _Impl::rbegin;
1134 using _Impl::cbegin;
1136 using _Impl::crbegin;
1142 using _Impl::max_size;
1145 using _Impl::emplace;
1146 using _Impl::emplace_hint;
1147 using _Impl::insert;
1148 using _Impl::insert_range;
1149 using _Impl::extract;
1150 using _Impl::replace;
1156 using _Impl::key_comp;
1157 using _Impl::value_comp;
1162 using _Impl::contains;
1163 using _Impl::lower_bound;
1164 using _Impl::upper_bound;
1165 using _Impl::equal_range;
1167 using _Impl::_M_erase_if;
1170 template<typename _KeyContainer,
1171 __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>
1172 flat_multiset(_KeyContainer, _Compare = _Compare())
1173 -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1175 template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>
1176 flat_multiset(_KeyContainer, _Alloc)
1177 -> flat_multiset<typename _KeyContainer::value_type,
1178 less<typename _KeyContainer::value_type>, _KeyContainer>;
1180 template<typename _KeyContainer, __not_allocator_like _Compare,
1181 __allocator_for<_KeyContainer> _Alloc>
1182 flat_multiset(_KeyContainer, _Compare, _Alloc)
1183 -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1185 template<typename _KeyContainer,
1186 __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>
1187 flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare())
1188 -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1190 template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>
1191 flat_multiset(sorted_equivalent_t, _KeyContainer, _Alloc)
1192 -> flat_multiset<typename _KeyContainer::value_type,
1193 less<typename _KeyContainer::value_type>, _KeyContainer>;
1195 template<typename _KeyContainer, __not_allocator_like _Compare,
1196 __allocator_for<_KeyContainer> _Alloc>
1197 flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Alloc)
1198 -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
1200 template<__has_input_iter_cat _InputIterator,
1201 __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>
1202 flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare())
1203 -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;
1205 template<__has_input_iter_cat _InputIterator,
1206 __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>
1207 flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())
1208 -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;
1210 template<ranges::input_range _Rg,
1211 __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,
1212 __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>>
1213 flat_multiset(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())
1214 -> flat_multiset<ranges::range_value_t<_Rg>, _Compare,
1215 vector<ranges::range_value_t<_Rg>,
1216 __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;
1218 template<ranges::input_range _Rg, __allocator_like _Alloc>
1219 flat_multiset(from_range_t, _Rg&&, _Alloc)
1220 -> flat_multiset<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>,
1221 vector<ranges::range_value_t<_Rg>,
1222 __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;
1224 template<typename _Key, __not_allocator_like _Compare = less<_Key>>
1225 flat_multiset(initializer_list<_Key>, _Compare = _Compare())
1226 -> flat_multiset<_Key, _Compare>;
1228 template<typename _Key, __not_allocator_like _Compare = less<_Key>>
1229 flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare())
1230 -> flat_multiset<_Key, _Compare>;
1232 template<typename _Key, typename _Compare,
1233 typename _KeyContainer, typename _Alloc>
1234 struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Alloc>
1235 : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>
1238 template<typename _Key, typename _Compare, typename _KeyContainer,
1239 typename _Predicate>
1240 _GLIBCXX26_CONSTEXPR
1241 typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type
1242 erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __c, _Predicate __pred)
1243 { return __c._M_erase_if(std::move(__pred)); }
1245 _GLIBCXX_END_NAMESPACE_VERSION
1247 #endif // __cpp_lib_flat_set
1248 #endif // _GLIBCXX_FLAT_SET