@@ -35,39 +35,19 @@ void conversion_test(T);
3535template <class T , class ... Args>
3636concept ImplicitlyConstructible = requires (Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
3737
38- void test () {
39- {
40- // The constructors in this subclause shall not participate in overload
41- // resolution unless uses_allocator_v<container_type, Alloc> is true
42-
43- using C = test_less<int >;
44- using A1 = test_allocator<int >;
45- using A2 = other_allocator<int >;
46- using V1 = std::vector<int , A1>;
47- using V2 = std::vector<int , A2>;
48- using M1 = std::flat_multiset<int , C, V1>;
49- using M2 = std::flat_multiset<int , C, V2>;
50- static_assert (std::is_constructible_v<M1, const V1&, const A1&>);
51- static_assert (std::is_constructible_v<M2, const V2&, const A2&>);
52- static_assert (!std::is_constructible_v<M1, const V1&, const A2&>);
53- static_assert (!std::is_constructible_v<M2, const V2&, const A1&>);
54-
55- static_assert (std::is_constructible_v<M1, const V1&, const C&, const A1&>);
56- static_assert (std::is_constructible_v<M2, const V2&, const C&, const A2&>);
57- static_assert (!std::is_constructible_v<M1, const V1&, const C&, const A2&>);
58- static_assert (!std::is_constructible_v<M2, const V2&, const C&, const A1&>);
59- }
38+ template <template <class ...> class KeyContainer >
39+ constexpr void test () {
6040 {
6141 // flat_multiset(container_type)
62- using M = std::flat_multiset<int >;
63- std::vector <int > ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
64- auto m = M (ks);
65- int expected[] = {1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 };
42+ using M = std::flat_multiset<int , std::less< int >, KeyContainer< int > >;
43+ KeyContainer <int > ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
44+ auto m = M (ks);
45+ int expected[] = {1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 };
6646 assert (std::ranges::equal (m, expected));
6747
6848 // explicit(false)
69- static_assert (std::is_constructible_v<M, const std::vector <int >&>);
70- static_assert (!ImplicitlyConstructible<M, const std::vector <int >&>);
49+ static_assert (std::is_constructible_v<M, const KeyContainer <int >&>);
50+ static_assert (!ImplicitlyConstructible<M, const KeyContainer <int >&>);
7151
7252 m = M (std::move (ks));
7353 assert (ks.empty ()); // it was moved-from
@@ -77,7 +57,7 @@ void test() {
7757 // flat_multiset(container_type)
7858 // move-only
7959 int expected[] = {3 , 3 , 2 , 1 };
80- using Ks = std::deque <MoveOnly, min_allocator<MoveOnly>>;
60+ using Ks = KeyContainer <MoveOnly, min_allocator<MoveOnly>>;
8161 using M = std::flat_multiset<MoveOnly, std::greater<MoveOnly>, Ks>;
8262 Ks ks;
8363 ks.push_back (1 );
@@ -92,8 +72,8 @@ void test() {
9272 // flat_multiset(container_type)
9373 // container's allocators are used
9474 using A = test_allocator<int >;
95- using M = std::flat_multiset<int , std::less<int >, std::deque <int , A>>;
96- auto ks = std::deque <int , A>({1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 }, A (5 ));
75+ using M = std::flat_multiset<int , std::less<int >, KeyContainer <int , A>>;
76+ auto ks = KeyContainer <int , A>({1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 }, A (5 ));
9777 auto m = M (std::move (ks));
9878 assert (ks.empty ()); // it was moved-from
9979 assert ((m == M{1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 }));
@@ -102,30 +82,30 @@ void test() {
10282 }
10383 {
10484 // flat_multiset(container_type, key_compare)
105- using C = test_less<int >;
106- using M = std::flat_multiset<int , C>;
107- std::vector <int > ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
108- auto m = M (ks, C (4 ));
85+ using C = test_less<int >;
86+ using M = std::flat_multiset<int , C, KeyContainer< int > >;
87+ KeyContainer <int > ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
88+ auto m = M (ks, C (4 ));
10989 assert (std::ranges::equal (m, std::vector<int >{1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 }));
11090 assert (m.key_comp () == C (4 ));
11191
11292 // explicit
113- static_assert (std::is_constructible_v<M, const std::vector <int >&, const C&>);
114- static_assert (!ImplicitlyConstructible<M, const std::vector <int >&, const C&>);
93+ static_assert (std::is_constructible_v<M, const KeyContainer <int >&, const C&>);
94+ static_assert (!ImplicitlyConstructible<M, const KeyContainer <int >&, const C&>);
11595 }
11696 {
11797 // flat_multiset(container_type , const Allocator&)
11898 using A = test_allocator<int >;
119- using M = std::flat_multiset<int , std::less<int >, std::deque <int , A>>;
120- auto ks = std::deque <int , A>({1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 }, A (5 ));
99+ using M = std::flat_multiset<int , std::less<int >, KeyContainer <int , A>>;
100+ auto ks = KeyContainer <int , A>({1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 }, A (5 ));
121101 auto m = M (ks, A (4 )); // replaces the allocators
122102 assert (!ks.empty ()); // it was an lvalue above
123103 assert ((m == M{1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 }));
124104 auto keys = M (m).extract ();
125105 assert (keys.get_allocator () == A (4 ));
126106
127107 // explicit(false)
128- static_assert (ImplicitlyConstructible<M, const std::deque <int , A>&, const A&>);
108+ static_assert (ImplicitlyConstructible<M, const KeyContainer <int , A>&, const A&>);
129109 M m2 = {ks, A (4 )}; // implicit ctor
130110 assert (!ks.empty ()); // it was an lvalue above
131111 assert (m2 == m);
@@ -134,19 +114,19 @@ void test() {
134114 }
135115 {
136116 // flat_multiset(container_type , const Allocator&)
137- using C = test_less<int >;
138- using A = test_allocator<int >;
139- using M = std::flat_multiset<int , C, std::vector <int , A>>;
140- std::vector <int , A> ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
141- auto m = M (ks, C (4 ), A (5 ));
142- assert (std::ranges::equal (m, std::vector <int , A>{1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 }));
117+ using C = test_less<int >;
118+ using A = test_allocator<int >;
119+ using M = std::flat_multiset<int , C, KeyContainer <int , A>>;
120+ KeyContainer <int , A> ks = {1 , 1 , 1 , 2 , 2 , 3 , 2 , 3 , 3 };
121+ auto m = M (ks, C (4 ), A (5 ));
122+ assert (std::ranges::equal (m, KeyContainer <int , A>{1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 }));
143123 assert (m.key_comp () == C (4 ));
144124 auto m_copy = m;
145125 auto keys = std::move (m_copy).extract ();
146126 assert (keys.get_allocator () == A (5 ));
147127
148128 // explicit(false)
149- static_assert (ImplicitlyConstructible<M, const std::vector <int , A>&, const A&>);
129+ static_assert (ImplicitlyConstructible<M, const KeyContainer <int , A>&, const A&>);
150130 M m2 = {ks, C (4 ), A (5 )};
151131 assert (m2 == m);
152132 assert (m2.key_comp () == C (4 ));
@@ -155,8 +135,44 @@ void test() {
155135 }
156136}
157137
138+ constexpr bool test () {
139+ {
140+ // The constructors in this subclause shall not participate in overload
141+ // resolution unless uses_allocator_v<container_type, Alloc> is true
142+
143+ using C = test_less<int >;
144+ using A1 = test_allocator<int >;
145+ using A2 = other_allocator<int >;
146+ using V1 = std::vector<int , A1>;
147+ using V2 = std::vector<int , A2>;
148+ using M1 = std::flat_multiset<int , C, V1>;
149+ using M2 = std::flat_multiset<int , C, V2>;
150+ static_assert (std::is_constructible_v<M1, const V1&, const A1&>);
151+ static_assert (std::is_constructible_v<M2, const V2&, const A2&>);
152+ static_assert (!std::is_constructible_v<M1, const V1&, const A2&>);
153+ static_assert (!std::is_constructible_v<M2, const V2&, const A1&>);
154+
155+ static_assert (std::is_constructible_v<M1, const V1&, const C&, const A1&>);
156+ static_assert (std::is_constructible_v<M2, const V2&, const C&, const A2&>);
157+ static_assert (!std::is_constructible_v<M1, const V1&, const C&, const A2&>);
158+ static_assert (!std::is_constructible_v<M2, const V2&, const C&, const A1&>);
159+ }
160+
161+ test<std::vector>();
162+
163+ #ifndef __cpp_lib_constexpr_deque
164+ if (!TEST_IS_CONSTANT_EVALUATED)
165+ #endif
166+ test<std::deque>();
167+
168+ return true ;
169+ }
170+
158171int main (int , char **) {
159172 test ();
173+ #if TEST_STD_VER >= 26
174+ static_assert (test ());
175+ #endif
160176
161177 return 0 ;
162178}
0 commit comments