Skip to content

Commit 59b682d

Browse files
committed
more tests
1 parent b05dacc commit 59b682d

38 files changed

+2423
-202
lines changed

libcxx/include/__flat_map/flat_map.h

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <__algorithm/ranges_upper_bound.h>
2222
#include <__compare/synth_three_way.h>
2323
#include <__concepts/convertible_to.h>
24+
#include <__concepts/swappable.h>
2425
#include <__config>
2526
#include <__flat_map/container_traits.h>
2627
#include <__flat_map/sorted_unique.h>
@@ -539,8 +540,8 @@ class flat_map {
539540
}
540541

541542
template <class _Kp>
542-
requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type> &&
543-
is_convertible_v<_Kp&&, const_iterator> && is_convertible_v<_Kp&&, iterator>
543+
requires(__is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type> &&
544+
!is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>)
544545
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](_Kp&& __x) {
545546
return try_emplace(std::forward<_Kp>(__x)).first->second;
546547
}
@@ -597,7 +598,7 @@ class flat_map {
597598
requires is_constructible_v<pair<key_type, mapped_type>, _Args...>
598599
_LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
599600
std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
600-
return __try_emplace_hint(__hint, std::move(__pair.first), std::move(__pair.second));
601+
return __try_emplace_hint(__hint, std::move(__pair.first), std::move(__pair.second)).first;
601602
}
602603

603604
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __x) { return emplace(__x); }
@@ -689,67 +690,67 @@ class flat_map {
689690
}
690691

691692
template <class _Kp, class... _Args>
692-
requires __is_compare_transparent && is_constructible_v<key_type, _Kp> &&
693-
is_constructible_v<mapped_type, _Args...> && is_convertible_v<_Kp&&, const_iterator> &&
694-
is_convertible_v<_Kp&&, iterator>
693+
requires(__is_compare_transparent && is_constructible_v<key_type, _Kp> &&
694+
is_constructible_v<mapped_type, _Args...> && !is_convertible_v<_Kp &&, const_iterator> &&
695+
!is_convertible_v<_Kp &&, iterator>)
695696
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> try_emplace(_Kp&& __key, _Args&&... __args) {
696697
return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
697698
}
698699

699700
template <class... _Args>
700701
requires is_constructible_v<mapped_type, _Args...>
701702
_LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) {
702-
return __try_emplace_hint(__hint, __key, std::forward<_Args>(__args)...);
703+
return __try_emplace_hint(__hint, __key, std::forward<_Args>(__args)...).first;
703704
}
704705

705706
template <class... _Args>
706707
requires is_constructible_v<mapped_type, _Args...>
707708
_LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) {
708-
return __try_emplace_hint(__hint, std::move(__key), std::forward<_Args>(__args)...);
709+
return __try_emplace_hint(__hint, std::move(__key), std::forward<_Args>(__args)...).first;
709710
}
710711

711712
template <class _Kp, class... _Args>
712713
requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type, _Args...>
713714
_LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
714-
return __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
715+
return __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...).first;
715716
}
716717

717718
template <class _Mapped>
718719
requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
719720
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(const key_type& __key, _Mapped&& __obj) {
720-
return __insert_or_assign_impl(__key, std::forward<_Mapped>(__obj));
721+
return __insert_or_assign(__key, std::forward<_Mapped>(__obj));
721722
}
722723

723724
template <class _Mapped>
724725
requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
725726
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(key_type&& __key, _Mapped&& __obj) {
726-
return __insert_or_assign_impl(std::move(__key), std::forward<_Mapped>(__obj));
727+
return __insert_or_assign(std::move(__key), std::forward<_Mapped>(__obj));
727728
}
728729

729730
template <class _Kp, class _Mapped>
730731
requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
731732
is_constructible_v<mapped_type, _Mapped>
732733
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(_Kp&& __key, _Mapped&& __obj) {
733-
return __insert_or_assign_impl(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
734+
return __insert_or_assign(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
734735
}
735736

736737
template <class _Mapped>
737738
requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
738739
_LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) {
739-
return __insert_or_assign_impl(__key, std::forward<_Mapped>(__obj), __hint).first;
740+
return __insert_or_assign(__hint, __key, std::forward<_Mapped>(__obj));
740741
}
741742

742743
template <class _Mapped>
743744
requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
744745
_LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) {
745-
return __insert_or_assign_impl(std::move(__key), std::forward<_Mapped>(__obj), __hint).first;
746+
return __insert_or_assign(__hint, std::move(__key), std::forward<_Mapped>(__obj));
746747
}
747748

748749
template <class _Kp, class _Mapped>
749750
requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
750751
is_constructible_v<mapped_type, _Mapped>
751752
_LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) {
752-
return __insert_or_assign_impl(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj), __hint).first;
753+
return __insert_or_assign(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
753754
}
754755

755756
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
@@ -788,15 +789,20 @@ class flat_map {
788789
}
789790

790791
_LIBCPP_HIDE_FROM_ABI void swap(flat_map& __y) noexcept {
791-
auto __guard = std::__make_exception_guard([&]() noexcept {
792+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
793+
try {
794+
# endif
795+
ranges::swap(__compare_, __y.__compare_);
796+
ranges::swap(__containers_.keys, __y.__containers_.keys);
797+
ranges::swap(__containers_.values, __y.__containers_.values);
798+
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
799+
} catch (...) {
800+
// todo: how can we tell the user that the swap is unsuccessful?
801+
// need to swallow the exception because the function is noexcept
792802
clear() /* noexcept */;
793803
__y.clear() /*noexcept*/;
794-
});
795-
using std::swap;
796-
swap(__compare_, __y.__compare_);
797-
swap(__containers_.keys, __y.__containers_.keys);
798-
swap(__containers_.values, __y.__containers_.values);
799-
__guard.__complete();
804+
}
805+
# endif
800806
}
801807

802808
_LIBCPP_HIDE_FROM_ABI void clear() noexcept {
@@ -807,6 +813,8 @@ class flat_map {
807813
// observers
808814
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
809815
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); }
816+
817+
// todo: can flat_map | std::views::keys be specialised?
810818
_LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; }
811819
_LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; }
812820

@@ -912,10 +920,10 @@ class flat_map {
912920

913921
private:
914922
struct __ctor_uses_allocator_tag {
915-
explicit __ctor_uses_allocator_tag() = default;
923+
explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default;
916924
};
917925
struct __ctor_uses_allocator_empty_tag {
918-
explicit __ctor_uses_allocator_empty_tag() = default;
926+
explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default;
919927
};
920928

921929
template <class _Allocator, class _KeyCont, class _MappedCont, class... _CompArg>
@@ -1085,18 +1093,20 @@ class flat_map {
10851093
}
10861094

10871095
template <class _Kp, class... _Args>
1088-
_LIBCPP_HIDE_FROM_ABI iterator __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
1096+
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
10891097
if (__is_hint_correct(__hint, __key)) {
10901098
if (__hint == cend() || __compare_(__key, __hint->first)) {
1091-
return __try_emplace_exact_hint(
1092-
__hint.__key_iter_, __hint.__mapped_iter_, std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
1099+
return {
1100+
__try_emplace_exact_hint(
1101+
__hint.__key_iter_, __hint.__mapped_iter_, std::forward<_Kp>(__key), std::forward<_Args>(__args)...),
1102+
true};
10931103
} else {
10941104
// key equals
10951105
auto __dist = __hint - cbegin();
1096-
return iterator(__containers_.keys.begin() + __dist, __containers_.values.begin() + __dist);
1106+
return {iterator(__containers_.keys.begin() + __dist, __containers_.values.begin() + __dist), false};
10971107
}
10981108
} else {
1099-
return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...).first;
1109+
return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
11001110
}
11011111
}
11021112

@@ -1139,15 +1149,24 @@ class flat_map {
11391149
return iterator(std::move(__key_it), std::move(__mapped_it));
11401150
}
11411151

1142-
template <class _Kp, class _Mapped, class... _Hint>
1143-
_LIBCPP_HIDE_FROM_ABI auto __insert_or_assign_impl(_Kp&& __key, _Mapped&& __mapped, _Hint&&... __hint) {
1144-
auto __r = try_emplace(__hint..., std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1152+
template <class _Kp, class _Mapped>
1153+
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) {
1154+
auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
11451155
if (!__r.second) {
11461156
__r.first->second = std::forward<_Mapped>(__mapped);
11471157
}
11481158
return __r;
11491159
}
11501160

1161+
template <class _Kp, class _Mapped>
1162+
_LIBCPP_HIDE_FROM_ABI iterator __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) {
1163+
auto __r = __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1164+
if (!__r.second) {
1165+
__r.first->second = std::forward<_Mapped>(__mapped);
1166+
}
1167+
return __r.first;
1168+
}
1169+
11511170
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
11521171
if constexpr (requires { __containers_.keys.reserve(__size); }) {
11531172
__containers_.keys.reserve(__size);
@@ -1175,8 +1194,8 @@ class flat_map {
11751194
[[no_unique_address]] key_compare __compare_;
11761195

11771196
struct __key_equiv {
1178-
__key_equiv(key_compare __c) : __comp_(__c) {}
1179-
bool operator()(const_reference __x, const_reference __y) const {
1197+
_LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
1198+
_LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
11801199
// todo
11811200
// LWG issue ? spec uses __x.first but zip_view no longer uses pair
11821201
return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ int main(int, char**) {
138138
assert(m.at(Transparent<int>{8}) == 8.5);
139139
assert(m.size() == 7);
140140
}
141+
{
142+
bool transparent_used = false;
143+
TransparentComparator c(transparent_used);
144+
std::flat_map<int, int, TransparentComparator> m(std::sorted_unique, {{1, 1}, {2, 2}, {3, 3}}, c);
145+
assert(!transparent_used);
146+
m.at(Transparent<int>{3});
147+
assert(transparent_used);
148+
}
141149

142150
return 0;
143151
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/index_key.pass.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,14 @@ int main(int, char**) {
9191
assert(m.size() == 8);
9292
}
9393

94+
{
95+
auto index_func = [](auto& m, auto key_arg, auto value_arg) {
96+
using FlatMap = std::decay_t<decltype(m)>;
97+
const typename FlatMap::key_type key = key_arg;
98+
const typename FlatMap::mapped_type value = value_arg;
99+
m[key] = value;
100+
};
101+
test_emplace_exception_guarantee(index_func);
102+
}
94103
return 0;
95104
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/index_rv_key.pass.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,14 @@ int main(int, char**) {
6565
assert(m.size() == 2);
6666
}
6767

68+
{
69+
auto index_func = [](auto& m, auto key_arg, auto value_arg) {
70+
using FlatMap = std::decay_t<decltype(m)>;
71+
typename FlatMap::key_type key = key_arg;
72+
const typename FlatMap::mapped_type value = value_arg;
73+
m[std::move(key)] = value;
74+
};
75+
test_emplace_exception_guarantee(index_func);
76+
}
6877
return 0;
6978
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/index_transparent.pass.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ int main(int, char**) {
109109
assert(m[six] == 6.5);
110110
assert(m.size() == 8);
111111
}
112-
112+
{
113+
bool transparent_used = false;
114+
TransparentComparator c(transparent_used);
115+
std::flat_map<int, int, TransparentComparator> m(std::sorted_unique, {{1, 1}, {2, 2}, {3, 3}}, c);
116+
assert(!transparent_used);
117+
m[ConvertibleTransparent<int>{3}];
118+
assert(transparent_used);
119+
}
120+
{
121+
auto index_func = [](auto& m, auto key_arg, auto value_arg) {
122+
using FlatMap = std::decay_t<decltype(m)>;
123+
using Key = typename FlatMap::key_type;
124+
const typename FlatMap::mapped_type value = value_arg;
125+
m[ConvertibleTransparent<Key>{key_arg}] = value;
126+
};
127+
test_emplace_exception_guarantee(index_func);
128+
}
113129
return 0;
114130
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.modifiers/clear.pass.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,21 @@
2020
#include <functional>
2121
#include <vector>
2222

23+
#include "../helpers.h"
2324
#include "test_macros.h"
2425
#include "min_allocator.h"
2526

27+
// test noexcept
28+
29+
template <class T>
30+
concept NoExceptClear = requires(T t) {
31+
{ t.clear() } noexcept;
32+
};
33+
34+
static_assert(NoExceptClear<std::flat_map<int, int>>);
35+
static_assert(
36+
NoExceptClear<std::flat_map<int, int, std::less<int>, ThrowOnMoveContainer<int>, ThrowOnMoveContainer<int>>>);
37+
2638
int main(int, char**) {
2739
{
2840
using M = std::flat_map<int, int>;

0 commit comments

Comments
 (0)