110 : inline_container::detail::compare_wrapper<Compare, Value>
111 , generic_ordering_from_three_way_compare<inline_set<Value, Capacity, Compare>> {
112 static_assert(std::is_nothrow_destructible<Value>::value,
"Destructors must not throw");
113 static_assert(std::is_nothrow_destructible<Compare>::value,
"Destructors must not throw");
115 is_invocable_r_v<
bool, Compare
const&, Value
const&, Value
const&> ||
116 is_invocable_r_v<strong_ordering, Compare
const&, Value
const&, Value
const&>,
117 "Compare must be invocable with two Values, and yield either a bool or a strong_ordering"
125 template <
typename OtherKey>
126 static constexpr bool
127 transparent_comparison_supported_for{::arene::base::is_transparent_comparator_for_v<Compare, Value
const&, OtherKey
const&> || ::arene::base::is_transparent_three_way_comparator_for_v<Compare, Value
const&, OtherKey
const&>};
132 using comparator_base = inline_container::detail::compare_wrapper<Compare, Value>;
136 using operator_base = generic_ordering_from_three_way_compare<inline_set<Value, Capacity, Compare>>;
143 template <
typename OtherKey = Value>
144 static constexpr bool comparison_is_noexcept{comparator_base::
template comparison_is_noexcept<OtherKey>};
149 using index_type = smallest_unsigned_integer_for<Capacity>;
154 using entry_type = optional<Value>;
160 using move_construct_source = conditional_t<
161 std::is_move_constructible<Compare>::value && std::is_move_constructible<Value>::value,
163 non_constructible_dummy>;
168 using move_assign_source = conditional_t<
169 std::is_move_assignable<Compare>::value && std::is_move_constructible<Value>::value,
171 non_constructible_dummy>;
176 using deleted_move_assign_source = conditional_t<
177 std::is_move_assignable<Compare>::value && std::is_move_constructible<Value>::value,
178 non_constructible_dummy,
184 using copy_assign_source = conditional_t<
185 std::is_copy_assignable<Compare>::value && std::is_copy_constructible<Value>::value,
187 non_constructible_dummy>;
192 using deleted_copy_assign_source = conditional_t<
193 std::is_copy_assignable<Compare>::value && std::is_copy_constructible<Value>::value,
194 non_constructible_dummy,
200 class iterator_impl : generic_ordering_from_three_way_compare<iterator_impl> {
203 inline_set
const* set_{
nullptr};
205 index_type element_index_{0};
209 using iterator_category = std::bidirectional_iterator_tag;
213 using value_type = Value;
218 using pointer = Value
const*;
223 using reference = Value
const&;
228 using difference_type = std::ptrdiff_t;
236 iterator_impl()
noexcept
237 : iterator_impl(inline_set_detail::set_passkey{},
nullptr, 0U) {}
247 iterator_impl(inline_set_detail::set_passkey, inline_set
const* set_to_iterate, index_type element)
noexcept
248 : generic_ordering_from_three_way_compare<iterator>(),
249 set_(set_to_iterate),
250 element_index_(element) {}
258 auto operator*()
const noexcept -> reference {
259 ARENE_PRECONDITION(set_ !=
nullptr);
260 return *(set_->values_[set_->indices_[element_index_]]);
267 auto operator->()
const noexcept -> pointer {
return &**
this; }
273 auto operator++()
noexcept -> iterator_impl& {
284 auto operator++(
int)
noexcept -> iterator_impl {
285 iterator temp{*
this};
296 auto operator--()
noexcept -> iterator_impl& {
297 ARENE_PRECONDITION(element_index_ > 0U);
308 auto operator--(
int)
noexcept -> iterator_impl {
309 iterator temp{*
this};
326 static auto three_way_compare(iterator_impl
const lhs, iterator_impl
const rhs)
noexcept -> strong_ordering {
327 ARENE_PRECONDITION(lhs.is_for(rhs.set_));
328 return compare_three_way{}(lhs.element_index_, rhs.element_index_);
337 auto is_for(inline_set
const* set_to_check)
const noexcept ->
bool {
return set_ == set_to_check; }
343 auto index(inline_set_detail::set_passkey)
const noexcept -> index_type {
return element_index_; }
350 using value_type = Value;
355 using value_compare = Compare;
360 using key_type = Value;
365 using key_compare = Compare;
370 using pointer = value_type*;
375 using const_pointer = value_type
const*;
380 using reference = value_type&;
385 using const_reference = value_type
const&;
390 using size_type = std::size_t;
395 using difference_type = std::ptrdiff_t;
400 using iterator = iterator_impl;
405 using const_iterator = iterator;
410 using reverse_iterator = ::arene::base::reverse_iterator<iterator>;
415 using const_reverse_iterator = ::arene::base::reverse_iterator<const_iterator>;
455 inline_set(std::initializer_list<Value> init, Compare
const& comp)
noexcept(
472 optional<inline_set> res{in_place};
473 if (!res->insert_elements_if_they_fit(init.begin(), init.end())) {
490 optional<inline_set> res{in_place, comp};
491 if (!res->insert_elements_if_they_fit(init.begin(), init.end())) {
513 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
514 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
516 inline_set(Iterator first, Iterator last)
noexcept(
517 std::is_nothrow_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value &&
518 std::is_nothrow_constructible<Compare>::value
540 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
541 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
543 inline_set(Iterator first, Iterator last, Compare
const& comp)
noexcept(
544 std::is_nothrow_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value &&
545 std::is_nothrow_copy_constructible<Compare>::value
565 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
566 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
568 ARENE_NODISCARD
static auto try_construct(Iterator first, Iterator last)
noexcept(
569 noexcept(inline_set{first, last}) && std::is_nothrow_move_constructible<inline_set>::value
570 ) -> optional<inline_set> {
571 optional<inline_set> res{in_place};
572 if (!res->insert_elements_if_they_fit(first, last)) {
593 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
594 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
596 ARENE_NODISCARD
static auto try_construct(Iterator first, Iterator last, Compare
const& comp)
noexcept(
597 noexcept(inline_set{first, last, comp}) && std::is_nothrow_move_constructible<inline_set>::value
598 ) -> optional<inline_set> {
599 optional<inline_set> res{in_place, comp};
600 if (!res->insert_elements_if_they_fit(first, last)) {
610 inline_set(inline_set
const&) =
default;
623 std::size_t OtherCapacity,
625 std::enable_if_t<(OtherCapacity < Capacity)>,
626 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
627 inline_set(inline_set<Value, OtherCapacity, Compare>
const& other
628 )
noexcept(std::is_nothrow_copy_constructible<Value>::value && std::is_nothrow_copy_constructible<Compare>::value)
629 : comparator_base(other.get_comparator_base(inline_set_detail::set_passkey{})),
645 std::size_t OtherCapacity,
647 std::enable_if_t<(OtherCapacity > Capacity)>,
648 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
649 inline_set(inline_set<Value, OtherCapacity, Compare>
const& other
650 )
noexcept(std::is_nothrow_copy_constructible<Value>::value && std::is_nothrow_copy_constructible<Compare>::value)
651 : comparator_base(other.get_comparator_base(inline_set_detail::set_passkey{})),
653 ARENE_PRECONDITION(other.size() <= max_size());
665 std::size_t OtherCapacity,
667 std::enable_if_t<(OtherCapacity <= Capacity)>,
668 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
669 ARENE_NODISCARD
static auto try_construct(inline_set<Value, OtherCapacity, Compare>
const& other
670 )
noexcept(
noexcept(inline_set{other})) -> optional<inline_set> {
671 return optional<inline_set>{in_place, other};
683 std::size_t OtherCapacity,
685 std::enable_if_t<(OtherCapacity > Capacity)>,
686 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
687 ARENE_NODISCARD
static auto try_construct(inline_set<Value, OtherCapacity, Compare>
const& other
688 )
noexcept(
noexcept(inline_set{other})) -> optional<inline_set> {
689 if (other.size() <= Capacity) {
690 return optional<inline_set>{in_place, other};
707 inline_set(move_construct_source&& other
708 )
noexcept(std::is_nothrow_move_constructible<Value>::value && std::is_nothrow_constructible<Compare>::value)
709 : comparator_base(std::move(
static_cast<comparator_base&>(other))),
711 number_of_active_elements_(other.number_of_active_elements_),
712 values_(move_values(other, std::make_index_sequence<Capacity>())),
713 indices_(std::move(other.indices_)) {}
727 std::size_t OtherCapacity,
729 std::enable_if_t<(OtherCapacity > Capacity)>,
730 std::enable_if_t<std::is_move_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
731 inline_set(inline_set<Value, OtherCapacity, Compare>&& other)
732 : comparator_base(std::move(other.get_comparator_base(inline_set_detail::set_passkey{}))),
734 ARENE_PRECONDITION(other.size() <= max_size());
735 do_move(std::move(other));
747 std::size_t OtherCapacity,
749 std::enable_if_t<(OtherCapacity < Capacity)>,
750 std::enable_if_t<std::is_move_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
751 inline_set(inline_set<Value, OtherCapacity, Compare>&& other
752 )
noexcept(std::is_nothrow_move_constructible<Value>::value && std::is_nothrow_move_constructible<Compare>::value)
753 : comparator_base(std::move(other.get_comparator_base(inline_set_detail::set_passkey{}))),
755 do_move(std::move(other));
768 std::size_t OtherCapacity,
770 std::enable_if_t<(OtherCapacity <= Capacity)>,
771 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
772 ARENE_NODISCARD
static auto try_construct(inline_set<Value, OtherCapacity, Compare>&& other
773 )
noexcept(
noexcept(inline_set{std::move(other)})) -> optional<inline_set> {
774 return optional<inline_set>{in_place, std::move(other)};
786 std::size_t OtherCapacity,
788 std::enable_if_t<(OtherCapacity > Capacity)>,
789 std::enable_if_t<std::is_copy_constructible<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
790 ARENE_NODISCARD
static auto try_construct(inline_set<Value, OtherCapacity, Compare>&& other
791 )
noexcept(
noexcept(inline_set{other})) -> optional<inline_set> {
792 if (other.size() <= Capacity) {
793 return optional<inline_set>{in_place, std::move(other)};
800 auto operator=(deleted_copy_assign_source
const& other) -> inline_set& =
delete;
816 if (
this != &other) {
817 static_cast<comparator_base&>(*
this) = other;
835 std::size_t OtherCapacity,
837 std::enable_if_t<(OtherCapacity > Capacity)>,
838 std::enable_if_t<std::is_copy_assignable<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
839 auto operator=(inline_set<Value, OtherCapacity, Compare>
const& other
840 )
noexcept(std::is_nothrow_copy_constructible<Value>::value && std::is_nothrow_copy_assignable<Compare>::value)
842 ARENE_PRECONDITION(other.size() <= max_size());
843 static_cast<comparator_base&>(*
this) = other.get_comparator_base(inline_set_detail::set_passkey{});
859 std::size_t OtherCapacity,
861 std::enable_if_t<(OtherCapacity < Capacity)>,
862 std::enable_if_t<std::is_copy_assignable<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
863 auto operator=(inline_set<Value, OtherCapacity, Compare>
const& other
864 )
noexcept(std::is_nothrow_copy_assignable<inline_set<Value, OtherCapacity, Compare>>::value) -> inline_set& {
865 static_cast<comparator_base&>(*
this) = other.get_comparator_base(inline_set_detail::set_passkey{});
873 auto operator=(deleted_move_assign_source&&) -> inline_set& =
delete;
891 if (
this != &other) {
892 static_cast<comparator_base&>(*
this) = std::move(other);
893 do_move(std::move(other));
912 std::size_t OtherCapacity,
914 std::enable_if_t<(OtherCapacity > Capacity)>,
915 std::enable_if_t<std::is_move_assignable<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
916 auto operator=(inline_set<Value, OtherCapacity, Compare>&& other) -> inline_set& {
917 ARENE_PRECONDITION(other.size() <= max_size());
918 static_cast<comparator_base&>(*
this) = std::move(other.get_comparator_base(inline_set_detail::set_passkey{}));
919 do_move(std::move(other));
935 std::size_t OtherCapacity,
937 std::enable_if_t<(OtherCapacity < Capacity)>,
938 std::enable_if_t<std::is_move_assignable<inline_set<Value, OtherCapacity, Compare>>::value>> =
nullptr>
939 auto operator=(inline_set<Value, OtherCapacity, Compare>&& other
940 )
noexcept(std::is_nothrow_move_assignable<inline_set<Value, OtherCapacity, Compare>>::value) -> inline_set& {
941 static_cast<comparator_base&>(*
this) = std::move(other.get_comparator_base(inline_set_detail::set_passkey{}));
942 do_move(std::move(other));
949 ARENE_NODISCARD
auto empty()
const noexcept ->
bool {
return number_of_active_elements_ == 0U; }
953 auto size()
const noexcept -> std::size_t {
return number_of_active_elements_; }
960 static constexpr std::integral_constant<size_type, Capacity> capacity{};
976 return comparator_base::get_comparator();
982 return comparator_base::get_comparator();
990 return do_find(value_to_find);
997 return do_find(value_to_find);
1005 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1006 auto find(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> iterator {
1007 return do_find(value);
1015 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1016 auto find(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> const_iterator {
1017 return do_find(value);
1025 auto contains(Value
const& value_to_check)
const noexcept(comparison_is_noexcept<>) ->
bool {
1026 return do_contains(value_to_check);
1035 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1036 auto contains(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) ->
bool {
1037 return do_contains(value);
1044 auto count(Value
const& value_to_count)
const noexcept(comparison_is_noexcept<>) -> std::size_t {
1045 return do_count(value_to_count);
1053 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1054 auto count(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> std::size_t {
1055 return do_count(value);
1063 auto lower_bound(Value
const& value_to_find)
noexcept(comparison_is_noexcept<>) -> iterator {
1064 return do_lower_bound(value_to_find);
1071 auto lower_bound(Value
const& value_to_find)
const noexcept(comparison_is_noexcept<>) -> const_iterator {
1072 return do_lower_bound(value_to_find);
1081 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1082 auto lower_bound(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> iterator {
1083 return do_lower_bound(value);
1092 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1093 auto lower_bound(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> const_iterator {
1094 return do_lower_bound(value);
1102 auto upper_bound(Value
const& value_to_find)
noexcept(comparison_is_noexcept<>) -> iterator {
1103 return do_upper_bound(value_to_find);
1111 auto upper_bound(Value
const& value_to_find)
const noexcept(comparison_is_noexcept<>) -> const_iterator {
1112 return do_upper_bound(value_to_find);
1121 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1122 auto upper_bound(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> iterator {
1123 return do_upper_bound(value);
1132 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1133 auto upper_bound(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> const_iterator {
1134 return do_upper_bound(value);
1143 auto equal_range(Value
const& value_to_find)
noexcept(comparison_is_noexcept<>) -> std::pair<iterator, iterator> {
1144 return do_equal_range(value_to_find);
1152 auto equal_range(Value
const& value_to_find)
const noexcept(comparison_is_noexcept<>)
1153 -> std::pair<const_iterator, const_iterator> {
1154 return do_equal_range(value_to_find);
1164 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1165 auto equal_range(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> std::pair<iterator, iterator> {
1166 return do_equal_range(value);
1176 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1177 auto equal_range(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>)
1178 -> std::pair<const_iterator, const_iterator> {
1179 return do_equal_range(value);
1195 auto insert(Value
const& value_to_insert
1196 )
noexcept(comparison_is_noexcept<> && std::is_nothrow_copy_constructible<Value>::value)
1197 -> std::pair<iterator,
bool> {
1198 return internal_insert(value_to_insert);
1214 auto insert(Value&& value_to_insert
1215 )
noexcept(comparison_is_noexcept<> && std::is_nothrow_move_constructible<Value>::value)
1216 -> std::pair<iterator,
bool> {
1217 return internal_insert(std::move(value_to_insert));
1235 typename SfinaeKey = Value,
1237 std::enable_if_t<transparent_comparison_supported_for<OtherKey>>,
1238 std::enable_if_t<!std::is_integral<SfinaeKey>::value>,
1239 std::enable_if_t<std::is_constructible<Value, OtherKey&&>::value>> =
nullptr>
1240 auto insert(OtherKey&& value
1241 )
noexcept(comparison_is_noexcept<OtherKey> && std::is_nothrow_constructible<Value, OtherKey&&>::value)
1242 -> std::pair<iterator,
bool> {
1243 return internal_insert(std::forward<OtherKey>(value));
1258 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
1259 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
1261 void insert(Iterator first, Iterator last)
noexcept(std::is_nothrow_constructible<Value,
decltype(*first)>::value) {
1262 for (
decltype(
auto) element : arene::base::make_subrange(first, last)) {
1263 std::ignore = insert(std::forward<
decltype(element)>(element));
1275 void insert(std::initializer_list<Value> init) { insert(init.begin(), init.end()); }
1280 auto begin()
const noexcept -> const_iterator {
return make_iterator(*
this, 0U); }
1283 auto cbegin()
const noexcept -> const_iterator {
return make_iterator(*
this, 0U); }
1287 auto end()
const noexcept -> const_iterator {
return make_iterator(*
this, number_of_active_elements_); }
1290 auto cend()
const noexcept -> const_iterator {
return make_iterator(*
this, number_of_active_elements_); }
1294 auto rbegin()
const noexcept -> const_reverse_iterator {
return const_reverse_iterator(end()); }
1297 auto crbegin()
const noexcept -> const_reverse_iterator {
return const_reverse_iterator(end()); }
1302 auto rend()
const noexcept -> const_reverse_iterator {
return const_reverse_iterator(begin()); }
1306 auto crend()
const noexcept -> const_reverse_iterator {
return const_reverse_iterator(begin()); }
1319 typename... ArgTypes,
1320 constraints<std::enable_if_t<std::is_constructible<Value, ArgTypes&&...>::value>> =
nullptr>
1321 auto emplace(ArgTypes&&... args) -> std::pair<iterator,
bool> {
1322 if (number_of_active_elements_ == Capacity) {
1323 Value
const value{std::forward<ArgTypes>(args)...};
1324 auto const pos_info = lower_bound_index(value);
1325 ARENE_PRECONDITION(pos_info.order == strong_ordering::equal);
1326 return {make_iterator(*
this, pos_info.index),
false};
1328 auto const new_index = indices_[number_of_active_elements_];
1329 auto& potentially_inserted_element = values_[new_index];
1330 potentially_inserted_element.emplace(std::forward<ArgTypes>(args)...);
1331 optional_resetter<Value> destroy_if_not_inserted{potentially_inserted_element};
1332 auto const pos_info = lower_bound_index(*potentially_inserted_element);
1333 bool const do_insert{pos_info.order != strong_ordering::equal};
1335 insert_index_at(pos_info.index, new_index);
1336 destroy_if_not_inserted.dismiss();
1338 return {make_iterator(*
this, pos_info.index), do_insert};
1350 auto erase(Value
const& value_to_erase)
noexcept(comparison_is_noexcept<>) -> size_type {
1351 return do_erase(value_to_erase);
1358 template <
typename OtherKey, constraints<std::enable_if_t<transparent_comparison_supported_for<OtherKey>>> =
nullptr>
1359 auto erase(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> size_type {
1360 return do_erase(value);
1367 auto erase(iterator pos)
noexcept -> iterator {
1368 ARENE_PRECONDITION(pos.is_for(
this));
1369 auto const index = pos.index(inline_set_detail::set_passkey{});
1370 ARENE_PRECONDITION(index <= number_of_active_elements_);
1371 std::ignore = erase_at_index(index);
1380 auto erase(iterator first, iterator last)
noexcept -> iterator {
1381 ARENE_PRECONDITION(first.is_for(
this) && last.is_for(
this));
1382 index_type
const first_index{first.index(inline_set_detail::set_passkey{})};
1383 index_type
const last_index{last.index(inline_set_detail::set_passkey{})};
1384 ARENE_PRECONDITION((first_index <= last_index) && (last_index <= size()));
1385 std::ignore = erase_index_range(first_index,
static_cast<index_type>(last_index - first_index));
1392 void clear()
noexcept { std::ignore = erase_index_range(0U, number_of_active_elements_); }
1402 template <size_type OtherCapacity>
1403 ARENE_NODISCARD
static auto
1404 fast_inequality_check(inline_set
const& lhs, inline_set<Value, OtherCapacity, Compare>
const& rhs)
noexcept
1405 -> inequality_heuristic {
1406 return lhs.size() == rhs.size() ? inequality_heuristic::may_be_equal_or_not_equal
1407 : inequality_heuristic::definitely_not_equal;
1427 size_type OtherCapacity,
1428 typename SfinaeKey = key_type,
1429 constraints<std::enable_if_t<compare_three_way_supported_v<SfinaeKey>>> =
nullptr>
1430 ARENE_NODISCARD
static auto
1431 three_way_compare(inline_set
const& lhs, inline_set<Value, OtherCapacity, Compare>
const& rhs)
noexcept
1432 -> strong_ordering {
1433 return ::arene::base::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1441 auto get_comparator_base(inline_set_detail::set_passkey)
noexcept -> comparator_base& {
return *
this; }
1448 auto get_comparator_base(inline_set_detail::set_passkey)
const noexcept -> comparator_base
const& {
return *
this; }
1457 auto entry_at_index(inline_set_detail::set_passkey, index_type index)
noexcept -> entry_type& {
1458 return values_[indices_[index]];
1468 auto entry_at_index(inline_set_detail::set_passkey, index_type index)
const noexcept -> entry_type
const& {
1469 return values_[indices_[index]];
1476 using storage_type = array<entry_type, Capacity>;
1479 index_type number_of_active_elements_{0};
1482 storage_type values_{};
1487 array<index_type, Capacity> indices_{sequential_values<index_type, Capacity>};
1500 std::enable_if_t<base::is_input_iterator_v<Iterator>>,
1501 std::enable_if_t<std::is_constructible<Value,
typename std::iterator_traits<Iterator>::reference>::value>> =
1503 auto insert_elements_if_they_fit(Iterator first, Iterator last)
noexcept(
1504 comparison_is_noexcept<> && std::is_nothrow_copy_constructible<Value>::value
1506 while (first != last) {
1507 if (size() < Capacity) {
1508 std::ignore = insert(*first);
1509 }
else if (!contains(*first)) {
1514 arene::base::advance(first, 1);
1529 template <
typename SelfType, constraints<std::enable_if_t<decays_to_v<SelfType, inline_set>>> =
nullptr>
1530 static auto make_iterator(SelfType&& self, index_type index)
noexcept -> iterator {
1531 return iterator_impl{inline_set_detail::set_passkey{}, &self, index};
1546 template <
typename SelfType, constraints<std::enable_if_t<decays_to_v<SelfType, inline_set>>> =
nullptr>
1548 make_find_iterator(SelfType&& self, inline_container::detail::lower_bound_index_info<index_type> lb_info)
noexcept
1550 if (lb_info.order == strong_ordering::equal) {
1551 return make_iterator(std::forward<SelfType>(self), lb_info.index);
1562 template <
typename OtherKey>
1563 auto do_find(OtherKey
const& value)
const -> iterator {
1564 return make_find_iterator(*
this, lower_bound_index(value));
1573 template <
typename OtherKey>
1574 auto do_contains(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) ->
bool {
1575 return do_find(value) != end();
1583 template <
typename OtherKey>
1584 auto do_count(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> std::size_t {
1585 return static_cast<std::size_t>(do_contains(value));
1593 template <
typename OtherKey>
1594 auto do_lower_bound(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> iterator {
1595 return make_iterator(*
this, lower_bound_index(value).index);
1606 template <
typename SelfType, constraints<std::enable_if_t<decays_to_v<SelfType, inline_set>>> =
nullptr>
1607 static auto make_upper_bound_iterator(
1609 inline_container::detail::lower_bound_index_info<index_type> lb_info
1610 )
noexcept -> iterator {
1611 if (lb_info.order == strong_ordering::equal) {
1614 return make_iterator(std::forward<SelfType>(self), lb_info.index);
1624 template <
typename OtherKey>
1625 auto do_upper_bound(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>) -> iterator {
1626 return make_upper_bound_iterator(*
this, lower_bound_index(value));
1642 template <
typename SelfType, constraints<std::enable_if_t<decays_to_v<SelfType, inline_set>>> =
nullptr>
1644 make_equal_range_iterator(SelfType&& self, inline_container::detail::lower_bound_index_info<index_type> lb_info)
1645 -> std::pair<iterator, iterator> {
1646 auto first = make_find_iterator(std::forward<SelfType>(self), lb_info);
1647 auto last = first == self.end() ? first : ::arene::base::next(first);
1648 return std::make_pair(first, last);
1664 template <
typename OtherKey>
1665 auto do_equal_range(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>)
1666 -> std::pair<iterator, iterator> {
1667 return make_equal_range_iterator(*
this, lower_bound_index(value));
1677 template <
typename OtherKey>
1678 auto lower_bound_index(OtherKey
const& value)
const noexcept(comparison_is_noexcept<OtherKey>)
1679 -> inline_container::detail::lower_bound_index_info<index_type> {
1680 auto const compare = [
this](key_type
const& lhs, OtherKey
const& rhs)
noexcept(comparison_is_noexcept<OtherKey>) {
1681 return this->key_ordering(lhs, rhs);
1683 auto const accessor = [
this](index_type
const index)
noexcept -> key_type
const& {
1684 return *(
this->entry_at_index(inline_set_detail::set_passkey{}, index));
1686 return inline_container::detail::lower_bound_index<key_type, OtherKey, index_type>(
1688 number_of_active_elements_,
1699 template <
typename OtherKey>
1700 auto do_erase(OtherKey
const& value)
noexcept(comparison_is_noexcept<OtherKey>) -> size_type {
1701 return static_cast<size_type>(erase_at_index(do_find(value).index(inline_set_detail::set_passkey{})) != end());
1710 template <
typename V>
1711 void insert_at(index_type pos, V&& value)
noexcept(std::is_nothrow_constructible<Value, V&&>::value) {
1712 auto const new_index = indices_[number_of_active_elements_];
1713 values_[new_index].emplace(std::forward<V>(value));
1714 insert_index_at(pos, new_index);
1723 void insert_index_at(index_type pos, index_type new_index)
noexcept {
1724 for (index_type i{number_of_active_elements_}; i != pos; --i) {
1725 indices_[i] = indices_[
static_cast<index_type>(i - 1U)];
1727 indices_[pos] = new_index;
1728 ++number_of_active_elements_;
1744 template <
typename V>
1745 auto internal_insert(V&& value
1746 )
noexcept(comparison_is_noexcept<V> && std::is_nothrow_constructible<Value, V&&>::value)
1747 -> std::pair<iterator,
bool> {
1748 auto const pos_info = lower_bound_index(value);
1749 auto const do_insert = pos_info.order != strong_ordering::equal;
1751 insert_at(pos_info.index, std::forward<V>(value));
1753 return {make_iterator(*
this, pos_info.index), do_insert};
1762 auto erase_at_index(index_type index)
noexcept -> iterator {
1763 return index < number_of_active_elements_ ? erase_index_range(index, 1U) : end();
1771 auto erase_index_range(index_type from, index_type count_to_erase)
noexcept -> iterator {
1772 index_type last_index{
static_cast<index_type>(from + count_to_erase)};
1773 for (index_type index{from}; index < last_index; ++index) {
1774 entry_at_index(inline_set_detail::set_passkey{}, index).reset();
1776 std::ignore = arene::base::rotate(
1777 indices_.begin() + from,
1778 indices_.begin() + last_index,
1779 indices_.begin() + number_of_active_elements_
1781 number_of_active_elements_ =
static_cast<index_type>(number_of_active_elements_ - (last_index - from));
1783 return make_iterator(*
this, from);
1792 static auto move_value(entry_type& other)
noexcept(std::is_nothrow_move_constructible<value_type>::value)
1794 entry_type res{std::move(other)};
1805 template <std::size_t... Indices>
1806 static auto move_values(inline_set& source, std::index_sequence<Indices...>) -> storage_type {
1808 auto const clear_on_exit = clear_on_scope_exit(source);
1810 return {{move_value(source.values_[Indices])...}};
1821 template <std::size_t OtherCapacity, std::size_t... Indices>
1822 static auto move_values(inline_set<Value, OtherCapacity, Compare>& source, std::index_sequence<Indices...>)
1824 auto const clear_on_exit = clear_on_scope_exit(source);
1825 return {{move_value(source.entry_at_index(inline_set_detail::set_passkey{}, Indices))...}};
1834 template <std::size_t OtherCapacity>
1835 static auto clear_on_scope_exit(inline_set<Value, OtherCapacity, Compare>& source)
noexcept ->
decltype(
auto) {
1836 return on_scope_exit(
1837 [&source]()
noexcept { source.clear(); }
1849 auto reset_trailing_values_on_scope_exit(index_type end_index)
noexcept ->
decltype(
auto) {
1850 return on_scope_exit([
this, end_index]()
noexcept {
1851 for (index_type idx =
this->number_of_active_elements_; idx < end_index; ++idx) {
1852 this->entry_at_index(inline_set_detail::set_passkey{}, idx).reset();
1869 template <
typename OtherSet>
1870 void do_copy(OtherSet
const& other
1871 )
noexcept(std::is_nothrow_copy_constructible<OtherSet>::value && std::is_nothrow_copy_assignable<OtherSet>::value) {
1872 do_assignment(other);
1887 template <
typename OtherSet>
1888 void do_move(OtherSet&& other
1889 )
noexcept(std::is_nothrow_move_constructible<OtherSet>::value && std::is_nothrow_move_assignable<OtherSet>::value) {
1891 auto const clear_on_exit = clear_on_scope_exit(other);
1893 do_assignment(std::forward<OtherSet>(other));
1910 template <
typename OtherSet>
1911 void do_assignment(OtherSet&& other)
noexcept(
1912 std::is_nothrow_constructible<OtherSet, OtherSet&&>::value &&
1913 std::is_nothrow_assignable<OtherSet&, OtherSet&&>::value
1916 auto const reset_trailing_values = reset_trailing_values_on_scope_exit(number_of_active_elements_);
1918 number_of_active_elements_ = 0U;
1919 while (number_of_active_elements_ != other.size()) {
1920 this->entry_at_index(inline_set_detail::set_passkey{}, number_of_active_elements_)
1921 .emplace(forward_like<OtherSet>(
1922 *other.entry_at_index(inline_set_detail::set_passkey{}, number_of_active_elements_)
1924 ++number_of_active_elements_;