10
10
11
11
// <flat_set>
12
12
13
- // template<class K> pair<iterator, bool> insert(P && x);
14
- // template<class K> iterator insert(const_iterator hint, P && x);
13
+ // template<class K> pair<iterator, bool> insert(K && x);
14
+ // template<class K> iterator insert(const_iterator hint, K && x);
15
15
16
16
#include < algorithm>
17
17
#include < compare>
27
27
#include " test_iterators.h"
28
28
#include " min_allocator.h"
29
29
30
- // Constraints: is_constructible_v<value_type, K> is true.
30
+ // Constraints: The qualified-id Compare::is_transparent is valid and denotes a type. is_constructible_v<value_type, K> is true.
31
31
template <class M , class ... Args>
32
32
concept CanInsert = requires(M m, Args&&... args) { m.insert (std::forward<Args>(args)...); };
33
33
34
- using Set = std::flat_set<int >;
35
- using Iter = Set::const_iterator;
34
+ using TransparentSet = std::flat_set<int , TransparentComparator>;
35
+ using TransparentSetIter = typename TransparentSet::iterator;
36
+ static_assert (CanInsert<TransparentSet, ExplicitlyConvertibleTransparent<int >>);
37
+ static_assert (CanInsert<TransparentSet, TransparentSetIter, ExplicitlyConvertibleTransparent<int >>);
38
+ static_assert (!CanInsert<TransparentSet, NonConvertibleTransparent<int >>);
39
+ static_assert (!CanInsert<TransparentSet, TransparentSetIter, NonConvertibleTransparent<int >>);
36
40
37
- static_assert (CanInsert<Set, short &&>);
38
- static_assert (CanInsert<Set, Iter, short &&>);
39
- static_assert (!CanInsert<Set, std::string>);
40
- static_assert (!CanInsert<Set, Iter, std::string>);
41
-
42
- static int expensive_comparisons = 0 ;
43
- static int cheap_comparisons = 0 ;
44
-
45
- struct CompareCounter {
46
- int i_ = 0 ;
47
- CompareCounter (int i) : i_(i) {}
48
- friend auto operator <=>(const CompareCounter& x, const CompareCounter& y) {
49
- expensive_comparisons += 1 ;
50
- return x.i_ <=> y.i_ ;
51
- }
52
- bool operator ==(const CompareCounter&) const = default ;
53
- friend auto operator <=>(const CompareCounter& x, int y) {
54
- cheap_comparisons += 1 ;
55
- return x.i_ <=> y;
56
- }
57
- };
41
+ using NonTransparentSet = std::flat_set<int >;
42
+ using NonTransparentSetIter = typename NonTransparentSet::iterator;
43
+ static_assert (!CanInsert<NonTransparentSet, ExplicitlyConvertibleTransparent<int >>);
44
+ static_assert (!CanInsert<NonTransparentSet, NonTransparentSetIter, ExplicitlyConvertibleTransparent<int >>);
45
+ static_assert (!CanInsert<NonTransparentSet, NonConvertibleTransparent<int >>);
46
+ static_assert (!CanInsert<NonTransparentSet, NonTransparentSetIter, NonConvertibleTransparent<int >>);
58
47
59
48
template <class KeyContainer >
60
49
void test_one () {
61
50
using Key = typename KeyContainer::value_type;
62
- using M = std::flat_set<Key, std::less<Key> , KeyContainer>;
51
+ using M = std::flat_set<Key, TransparentComparator , KeyContainer>;
63
52
64
- const int expected[] = {1 , 2 , 3 , 4 , 5 };
65
53
{
66
- // insert(P&&)
67
- // Unlike flat_set, here we can't use key_compare to compare value_type versus P,
68
- // so we must eagerly convert to value_type.
69
- M m = {1 , 2 , 4 , 5 };
70
- expensive_comparisons = 0 ;
71
- cheap_comparisons = 0 ;
72
- std::same_as<std::pair<typename M::iterator, bool >> auto p = m.insert (3 ); // conversion happens first
73
- assert (expensive_comparisons >= 2 );
74
- assert (cheap_comparisons == 0 );
75
- assert (p == std::make_pair (m.begin () + 2 , true ));
76
- assert (std::ranges::equal (m, expected));
77
- }
78
- {
79
- // insert(const_iterator, P&&)
80
- M m = {1 , 2 , 4 , 5 };
81
- expensive_comparisons = 0 ;
82
- cheap_comparisons = 0 ;
83
- std::same_as<typename M::iterator> auto it = m.insert (m.begin (), 3 );
84
- assert (expensive_comparisons >= 2 );
85
- assert (cheap_comparisons == 0 );
86
- assert (it == m.begin () + 2 );
87
- assert (std::ranges::equal (m, expected));
88
- }
89
- {
90
- // insert(value_type&&)
91
- M m = {1 , 2 , 4 , 5 };
92
- expensive_comparisons = 0 ;
93
- cheap_comparisons = 0 ;
94
- std::same_as<std::pair<typename M::iterator, bool >> auto p = m.insert (3 ); // conversion happens last
95
- assert (expensive_comparisons >= 2 );
96
- assert (cheap_comparisons == 0 );
97
- assert (p == std::make_pair (m.begin () + 2 , true ));
98
- assert (std::ranges::equal (m, expected));
99
- }
100
- {
101
- // insert(const_iterator, value_type&&)
102
- M m = {1 , 2 , 4 , 5 };
103
- expensive_comparisons = 0 ;
104
- cheap_comparisons = 0 ;
105
- std::same_as<typename M::iterator> auto it = m.insert (m.begin (), 3 );
106
- assert (expensive_comparisons >= 2 );
107
- assert (cheap_comparisons == 0 );
108
- assert (it == m.begin () + 2 );
109
- assert (std::ranges::equal (m, expected));
110
- }
111
- {
112
- // emplace(Args&&...)
113
- M m = {1 , 2 , 4 , 5 };
114
- expensive_comparisons = 0 ;
115
- cheap_comparisons = 0 ;
116
- std::same_as<std::pair<typename M::iterator, bool >> auto p = m.emplace (3 ); // conversion happens first
117
- assert (expensive_comparisons >= 2 );
118
- assert (cheap_comparisons == 0 );
119
- assert (p == std::make_pair (m.begin () + 2 , true ));
120
- assert (std::ranges::equal (m, expected));
54
+ const int expected[] = {1 , 2 , 3 , 4 , 5 };
55
+
56
+ {
57
+ // insert(K&&)
58
+ bool transparent_used = false ;
59
+ M m{{1 , 2 , 4 , 5 }, TransparentComparator{transparent_used}};
60
+ assert (!transparent_used);
61
+ std::same_as<std::pair<typename M::iterator, bool >> decltype (auto ) r =
62
+ m.insert (ExplicitlyConvertibleTransparent<Key>{3 });
63
+ assert (transparent_used);
64
+ assert (r.first == m.begin () + 2 );
65
+ assert (r.second );
66
+ assert (std::ranges::equal (m, expected));
67
+ }
68
+ {
69
+ // insert(const_iterator, K&&)
70
+ bool transparent_used = false ;
71
+ M m{{1 , 2 , 4 , 5 }, TransparentComparator{transparent_used}};
72
+ assert (!transparent_used);
73
+ std::same_as<typename M::iterator> auto it = m.insert (m.begin (), ExplicitlyConvertibleTransparent<Key>{3 });
74
+ assert (transparent_used);
75
+ assert (it == m.begin () + 2 );
76
+ assert (std::ranges::equal (m, expected));
77
+ }
121
78
}
79
+
122
80
{
123
81
// was empty
124
- M m;
125
- std::same_as<std::pair<typename M::iterator, bool >> auto p = m.insert (3 );
126
- assert (p == std::make_pair (m.begin (), true ));
127
- M expected2 = {3 };
128
- assert (std::ranges::equal (m, expected2));
82
+ const int expected[] = {3 };
83
+ {
84
+ // insert(K&&)
85
+ bool transparent_used = false ;
86
+ M m{{}, TransparentComparator{transparent_used}};
87
+ assert (!transparent_used);
88
+ std::same_as<std::pair<typename M::iterator, bool >> decltype (auto ) r =
89
+ m.insert (ExplicitlyConvertibleTransparent<Key>{3 });
90
+ assert (!transparent_used); // no elements to compare against
91
+ assert (r.first == m.begin ());
92
+ assert (r.second );
93
+ assert (std::ranges::equal (m, expected));
94
+ }
95
+ {
96
+ // insert(const_iterator, K&&)
97
+ bool transparent_used = false ;
98
+ M m{{}, TransparentComparator{transparent_used}};
99
+ assert (!transparent_used);
100
+ std::same_as<typename M::iterator> auto it = m.insert (m.begin (), ExplicitlyConvertibleTransparent<Key>{3 });
101
+ assert (!transparent_used); // no elements to compare against
102
+ assert (it == m.begin ());
103
+ assert (std::ranges::equal (m, expected));
104
+ }
129
105
}
130
106
}
131
107
132
108
void test () {
133
- test_one<std::vector<CompareCounter >>();
134
- test_one<std::deque<CompareCounter >>();
135
- test_one<MinSequenceContainer<CompareCounter >>();
136
- test_one<std::vector<CompareCounter , min_allocator<CompareCounter >>>();
109
+ test_one<std::vector<int >>();
110
+ test_one<std::deque<int >>();
111
+ test_one<MinSequenceContainer<int >>();
112
+ test_one<std::vector<int , min_allocator<int >>>();
137
113
138
114
{
139
115
// no ambiguity between insert(pos, P&&) and insert(first, last)
@@ -153,26 +129,14 @@ void test_exception() {
153
129
{
154
130
auto insert_func = [](auto & m, auto key_arg) {
155
131
using FlatSet = std::decay_t <decltype (m)>;
156
- struct T {
157
- typename FlatSet::key_type key_;
158
- T (typename FlatSet::key_type key) : key_(key) {}
159
- operator typename FlatSet::value_type () const { return key_; }
160
- };
161
- T t (key_arg);
162
- m.insert (t);
132
+ m.insert (ExplicitlyConvertibleTransparent<typename FlatSet::key_type>{key_arg});
163
133
};
164
134
test_emplace_exception_guarantee (insert_func);
165
135
}
166
136
{
167
137
auto insert_func_iter = [](auto & m, auto key_arg) {
168
138
using FlatSet = std::decay_t <decltype (m)>;
169
- struct T {
170
- typename FlatSet::key_type key_;
171
- T (typename FlatSet::key_type key) : key_(key) {}
172
- operator typename FlatSet::value_type () const { return key_; }
173
- };
174
- T t (key_arg);
175
- m.insert (m.begin (), t);
139
+ m.insert (m.begin (), ExplicitlyConvertibleTransparent<typename FlatSet::key_type>{key_arg});
176
140
};
177
141
test_emplace_exception_guarantee (insert_func_iter);
178
142
}
0 commit comments