]>
Commit | Line | Data |
---|---|---|
43308b7e | 1 | // -*- C++ -*- |
2 | ||
fbd26352 | 3 | // Copyright (C) 2009-2019 Free Software Foundation, Inc. |
43308b7e | 4 | // |
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 terms | |
7 | // of the GNU General Public License as published by the Free Software | |
8 | // Foundation; either version 3, or (at your option) any later | |
9 | // version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, but | |
12 | // WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | ||
16 | // You should have received a copy of the GNU General Public License along | |
17 | // with this library; see the file COPYING3. If not see | |
18 | // <http://www.gnu.org/licenses/>. | |
19 | ||
20 | #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H | |
21 | #define _GLIBCXX_TESTSUITE_CONTAINERS_H | |
22 | ||
319d9891 | 23 | #include <bits/boost_concept_check.h> |
43308b7e | 24 | #include <cassert> |
25 | #include <testsuite_container_traits.h> | |
9fe2a042 | 26 | #include <utility> // for rel_ops. |
43308b7e | 27 | |
28 | // Container requirement testing. | |
29 | namespace __gnu_test | |
30 | { | |
31 | // Compile-time typedef testing. | |
32 | template<typename _Tp, bool _Bt = traits<_Tp>::is_container::value> | |
33 | struct basic_types | |
34 | { | |
35 | // Base container requirements (table 80) | |
36 | typedef _Tp test_type; | |
37 | typedef typename test_type::value_type value_type; | |
d0b5b304 | 38 | typedef typename test_type::pointer pointer; |
39 | typedef typename test_type::const_pointer const_pointer; | |
43308b7e | 40 | typedef typename test_type::reference reference; |
41 | typedef typename test_type::const_reference const_reference; | |
42 | typedef typename test_type::iterator iterator; | |
43 | typedef typename test_type::const_iterator const_iterator; | |
44 | typedef typename test_type::size_type size_type; | |
45 | typedef typename test_type::difference_type difference_type; | |
46 | }; | |
47 | ||
48 | // Conditional typedef testing, positive. | |
49 | template<typename _Tp, bool _Bt = traits<_Tp>::is_reversible::value> | |
50 | struct reversible_types | |
51 | { | |
52 | // Reversible container requirements (table 81) | |
53 | typedef _Tp test_type; | |
54 | typedef typename test_type::reverse_iterator reverse_iterator; | |
55 | typedef typename test_type::const_reverse_iterator const_reverse_iterator; | |
56 | }; | |
57 | ||
58 | template<typename _Tp, bool _Bt = traits<_Tp>::is_allocator_aware::value> | |
59 | struct allocator_aware_types | |
60 | { | |
4f4a327e | 61 | // _Alloc-aware requirements (table 82) |
43308b7e | 62 | typedef _Tp test_type; |
63 | typedef typename test_type::allocator_type allocator_type; | |
64 | }; | |
65 | ||
43308b7e | 66 | template<typename _Tp, bool _Bt = traits<_Tp>::is_associative::value> |
67 | struct associative_types | |
68 | { | |
69 | // Associative container requirements (table 85) | |
70 | typedef _Tp test_type; | |
71 | typedef typename test_type::key_type key_type; | |
72 | typedef typename test_type::key_compare key_compare; | |
73 | typedef typename test_type::value_compare value_compare; | |
74 | }; | |
75 | ||
76 | template<typename _Tp, bool = traits<_Tp>::is_unordered::value> | |
77 | struct unordered_types | |
78 | { | |
79 | // Unordered associative container requirements (table 87) | |
80 | typedef _Tp test_type; | |
81 | typedef typename test_type::key_type key_type; | |
82 | typedef typename test_type::hasher hasher; | |
83 | typedef typename test_type::key_equal key_equal; | |
84 | typedef typename test_type::local_iterator local_iterator; | |
85 | typedef typename test_type::const_local_iterator const_local_iterator; | |
86 | }; | |
87 | ||
88 | template<typename _Tp, bool _Bt = traits<_Tp>::is_mapped::value> | |
89 | struct mapped_types | |
90 | { | |
91 | typedef _Tp test_type; | |
92 | typedef typename test_type::mapped_type mapped_type; | |
93 | }; | |
94 | ||
95 | template<typename _Tp, bool = traits<_Tp>::is_adaptor::value> | |
96 | struct adaptor_types | |
97 | { | |
98 | // Container adaptor requirements. | |
99 | typedef _Tp test_type; | |
100 | typedef typename test_type::value_type value_type; | |
101 | typedef typename test_type::reference reference; | |
102 | typedef typename test_type::const_reference const_reference; | |
103 | typedef typename test_type::size_type size_type; | |
104 | typedef typename test_type::container_type container_type; | |
105 | }; | |
106 | ||
107 | // Conditional typedef testing, negative. | |
108 | template<typename _Tp> | |
109 | struct basic_types<_Tp, false> { }; | |
110 | ||
111 | template<typename _Tp> | |
d0b5b304 | 112 | struct adaptor_types<_Tp, false> { }; |
43308b7e | 113 | |
114 | template<typename _Tp> | |
d0b5b304 | 115 | struct reversible_types<_Tp, false> { }; |
43308b7e | 116 | |
117 | template<typename _Tp> | |
d0b5b304 | 118 | struct allocator_aware_types<_Tp, false> { }; |
43308b7e | 119 | |
120 | template<typename _Tp> | |
121 | struct associative_types<_Tp, false> { }; | |
122 | ||
123 | template<typename _Tp> | |
124 | struct unordered_types<_Tp, false> { }; | |
125 | ||
126 | template<typename _Tp> | |
127 | struct mapped_types<_Tp, false> { }; | |
128 | ||
43308b7e | 129 | // Primary template. |
130 | template<typename _Tp> | |
131 | struct types | |
132 | : basic_types<_Tp>, adaptor_types<_Tp>, reversible_types<_Tp>, | |
d0b5b304 | 133 | allocator_aware_types<_Tp>, associative_types<_Tp>, |
134 | unordered_types<_Tp>, mapped_types<_Tp> | |
43308b7e | 135 | { }; |
136 | ||
137 | ||
138 | // Run-time test for constant_iterator requirements. | |
139 | template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value> | |
140 | struct populate | |
141 | { | |
142 | populate(_Tp& container) | |
143 | { | |
cfcd3170 | 144 | // Avoid uninitialized warnings, requires DefaultContructible. |
145 | typedef typename _Tp::value_type value_type; | |
146 | container.insert(container.begin(), value_type()); | |
147 | container.insert(container.begin(), value_type()); | |
43308b7e | 148 | } |
149 | }; | |
150 | ||
151 | template<typename _Tp> | |
152 | struct populate<_Tp, false> | |
153 | { | |
154 | populate(_Tp& container) { } | |
155 | }; | |
156 | ||
157 | template<typename _Tp, bool = traits<_Tp>::is_reversible::value> | |
158 | struct reverse_members | |
159 | { | |
160 | reverse_members(_Tp& container) | |
161 | { | |
162 | assert( container.crbegin() == container.rbegin() ); | |
163 | assert( container.crend() == container.rend() ); | |
164 | assert( container.crbegin() != container.crend() ); | |
165 | } | |
166 | }; | |
167 | ||
168 | template<typename _Tp> | |
169 | struct reverse_members<_Tp, false> | |
170 | { | |
171 | reverse_members(_Tp& container) { } | |
172 | }; | |
173 | ||
9fe2a042 | 174 | template<typename _Iterator, |
175 | bool _Mutable, | |
176 | typename = typename std::iterator_traits<_Iterator>::iterator_category> | |
177 | struct iterator_concept_checks; | |
178 | ||
f505dfb9 | 179 | #if __cplusplus >= 201103L |
43308b7e | 180 | // DR 691. |
9fe2a042 | 181 | template<typename _Tp> |
43308b7e | 182 | struct forward_members_unordered |
183 | { | |
f505dfb9 | 184 | forward_members_unordered(const typename _Tp::value_type& v) |
43308b7e | 185 | { |
9fe2a042 | 186 | // Make sure that even if rel_ops is injected there is no ambiguity |
187 | // when comparing iterators. | |
188 | using namespace std::rel_ops; | |
189 | ||
43308b7e | 190 | typedef _Tp test_type; |
191 | test_type container; | |
192 | container.insert(v); | |
9fe2a042 | 193 | |
194 | iterator_concept_checks<typename _Tp::local_iterator, false> cc; | |
195 | iterator_concept_checks<typename _Tp::const_local_iterator, | |
196 | false> ccc; | |
197 | ||
43308b7e | 198 | assert( container.cbegin(0) == container.begin(0) ); |
199 | assert( container.cend(0) == container.end(0) ); | |
f505dfb9 | 200 | const auto bn = container.bucket(1); |
201 | auto clit = container.cbegin(bn); | |
202 | assert( clit != container.cend(bn) ); | |
203 | assert( clit != container.end(bn) ); | |
204 | assert( clit++ == container.cbegin(bn) ); | |
205 | assert( clit == container.end(bn) ); | |
206 | ||
207 | clit = container.cbegin(bn); | |
208 | assert( ++clit == container.cend(bn) ); | |
209 | ||
9fe2a042 | 210 | assert( container.begin(bn) != container.cend(bn) ); |
43308b7e | 211 | } |
212 | }; | |
f505dfb9 | 213 | #endif |
43308b7e | 214 | |
319d9891 | 215 | template<typename _Iterator> |
216 | struct iterator_concept_checks<_Iterator, false, | |
217 | std::forward_iterator_tag> | |
218 | { | |
219 | iterator_concept_checks() | |
220 | { | |
221 | using namespace __gnu_cxx; | |
222 | __function_requires<_ForwardIteratorConcept<_Iterator>>(); | |
223 | } | |
224 | }; | |
225 | ||
226 | template<typename _Iterator> | |
227 | struct iterator_concept_checks<_Iterator, true, | |
228 | std::forward_iterator_tag> | |
229 | { | |
230 | iterator_concept_checks() | |
231 | { | |
232 | using namespace __gnu_cxx; | |
233 | __function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>(); | |
234 | } | |
235 | }; | |
236 | ||
237 | template<typename _Iterator> | |
238 | struct iterator_concept_checks<_Iterator, false, | |
239 | std::bidirectional_iterator_tag> | |
240 | { | |
241 | iterator_concept_checks() | |
242 | { | |
243 | using namespace __gnu_cxx; | |
244 | __function_requires<_BidirectionalIteratorConcept<_Iterator>>(); | |
245 | } | |
246 | }; | |
247 | ||
248 | template<typename _Iterator> | |
249 | struct iterator_concept_checks<_Iterator, true, | |
250 | std::bidirectional_iterator_tag> | |
251 | { | |
252 | iterator_concept_checks() | |
253 | { | |
254 | using namespace __gnu_cxx; | |
255 | __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>(); | |
256 | } | |
257 | }; | |
258 | ||
259 | template<typename _Iterator> | |
260 | struct iterator_concept_checks<_Iterator, false, | |
261 | std::random_access_iterator_tag> | |
262 | { | |
263 | iterator_concept_checks() | |
264 | { | |
265 | using namespace __gnu_cxx; | |
266 | __function_requires<_RandomAccessIteratorConcept<_Iterator>>(); | |
267 | } | |
268 | }; | |
269 | ||
270 | template<typename _Iterator> | |
271 | struct iterator_concept_checks<_Iterator, true, | |
272 | std::random_access_iterator_tag> | |
273 | { | |
274 | iterator_concept_checks() | |
275 | { | |
276 | using namespace __gnu_cxx; | |
277 | __function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>(); | |
278 | } | |
279 | }; | |
280 | ||
9fe2a042 | 281 | template<typename _Tp> |
282 | struct forward_members | |
283 | { | |
284 | forward_members(_Tp& container) | |
285 | { | |
286 | // Make sure that even if rel_ops is injected there is no ambiguity | |
287 | // when comparing iterators. | |
288 | using namespace std::rel_ops; | |
289 | ||
290 | typedef traits<_Tp> traits_type; | |
291 | iterator_concept_checks<typename _Tp::iterator, | |
292 | !(traits_type::is_associative::value | |
293 | || traits_type::is_unordered::value)> cc; | |
294 | iterator_concept_checks<typename _Tp::const_iterator, false> ccc; | |
295 | ||
296 | assert( container.cbegin() == container.begin() ); | |
297 | assert( container.end() == container.cend() ); | |
298 | assert( container.cbegin() != container.cend() ); | |
299 | assert( container.cbegin() != container.end() ); | |
300 | assert( container.begin() != container.cend() ); | |
301 | } | |
302 | }; | |
303 | ||
304 | template<typename _Tp, | |
305 | typename | |
306 | = typename std::iterator_traits<typename _Tp::iterator>::iterator_category> | |
307 | struct category_members : forward_members<_Tp> | |
308 | { | |
309 | category_members(_Tp& container) | |
310 | : forward_members<_Tp>(container) | |
311 | { }; | |
312 | }; | |
313 | ||
314 | template<typename _Tp> | |
315 | struct category_members<_Tp, std::random_access_iterator_tag> | |
316 | : forward_members<_Tp> | |
317 | { | |
318 | category_members(_Tp& container) | |
319 | : forward_members<_Tp>(container) | |
320 | { | |
321 | // Make sure that even if rel_ops is injected there is no ambiguity | |
322 | // when comparing iterators. | |
323 | using namespace std::rel_ops; | |
324 | ||
325 | assert( !(container.begin() < container.begin()) ); | |
326 | assert( !(container.cbegin() < container.cbegin()) ); | |
327 | assert( !(container.cbegin() < container.begin()) ); | |
328 | assert( !(container.begin() < container.cbegin()) ); | |
329 | assert( container.begin() <= container.begin() ); | |
330 | assert( container.cbegin() <= container.cbegin() ); | |
331 | assert( container.cbegin() <= container.begin() ); | |
332 | assert( container.begin() <= container.cbegin() ); | |
333 | ||
334 | assert( !(container.begin() > container.begin()) ); | |
335 | assert( !(container.cbegin() > container.cbegin()) ); | |
336 | assert( !(container.cbegin() > container.begin()) ); | |
337 | assert( !(container.begin() > container.cbegin()) ); | |
338 | assert( container.begin() >= container.begin() ); | |
339 | assert( container.cbegin() >= container.cbegin() ); | |
340 | assert( container.cbegin() >= container.begin() ); | |
341 | assert( container.begin() >= container.cbegin() ); | |
342 | ||
343 | assert( container.begin() - container.begin() == 0 ); | |
344 | assert( container.cbegin() - container.cbegin() == 0 ); | |
345 | assert( container.cbegin() - container.begin() == 0 ); | |
346 | assert( container.begin() - container.cbegin() == 0 ); | |
347 | ||
348 | assert( container.begin() + 0 == container.begin() ); | |
349 | assert( container.cbegin() + 0 == container.cbegin() ); | |
350 | assert( 0 + container.begin() == container.begin() ); | |
351 | assert( 0 + container.cbegin() == container.cbegin() ); | |
352 | assert( container.begin() - 0 == container.begin() ); | |
353 | assert( container.cbegin() - 0 == container.cbegin() ); | |
354 | } | |
355 | }; | |
356 | ||
43308b7e | 357 | template<typename _Tp> |
358 | struct citerator | |
359 | { | |
360 | typedef _Tp test_type; | |
361 | typedef traits<test_type> traits_type; | |
362 | typedef typename test_type::value_type value_type; | |
363 | ||
364 | static test_type _S_container; | |
365 | ||
366 | // Unconditional. | |
9fe2a042 | 367 | struct members : category_members<_Tp> |
43308b7e | 368 | { |
9fe2a042 | 369 | members() : category_members<_Tp>(_S_container) |
370 | { } | |
43308b7e | 371 | }; |
372 | ||
373 | // Run test. | |
374 | citerator() | |
375 | { | |
376 | populate<test_type> p(_S_container); | |
9fe2a042 | 377 | members m1; |
43308b7e | 378 | reverse_members<test_type> m2(_S_container); |
379 | } | |
380 | }; | |
381 | ||
382 | template<typename _Tp> | |
383 | _Tp citerator<_Tp>::_S_container; | |
384 | ||
8544d95d | 385 | // DR 130 vs. C++98 vs. C++11. |
386 | // Defined in testsuite_shared.cc. | |
33b7ef52 | 387 | void |
8544d95d | 388 | erase_external(std::set<int>& s); |
389 | ||
33b7ef52 | 390 | void |
8544d95d | 391 | erase_external(std::multiset<int>& s); |
392 | ||
33b7ef52 | 393 | void |
8544d95d | 394 | erase_external(std::map<int, int>& s); |
395 | ||
33b7ef52 | 396 | void |
8544d95d | 397 | erase_external(std::multimap<int, int>& s); |
398 | ||
33b7ef52 | 399 | void |
8544d95d | 400 | erase_external_iterators(std::set<int>& s); |
401 | ||
33b7ef52 | 402 | void |
8544d95d | 403 | erase_external_iterators(std::multiset<int>& s); |
404 | ||
33b7ef52 | 405 | void |
8544d95d | 406 | erase_external_iterators(std::map<int, int>& s); |
407 | ||
33b7ef52 | 408 | void |
8544d95d | 409 | erase_external_iterators(std::multimap<int, int>& s); |
410 | ||
411 | // NB: "must be compiled with C++11" | |
412 | #if __cplusplus >= 201103L | |
413 | template<typename _Tp> | |
33b7ef52 | 414 | void |
8544d95d | 415 | linkage_check_cxx98_cxx11_erase(_Tp& container) |
416 | { | |
7b96e840 | 417 | // Crashing when external reference and internal reference symbols are |
8544d95d | 418 | // equivalently mangled but have different size return types in C++98 |
419 | // and C++11 signatures. | |
420 | erase_external(container); // C++98 | |
421 | container.erase(container.begin()); // C++11 | |
422 | } | |
423 | ||
424 | template<typename _Tp> | |
33b7ef52 | 425 | void |
8544d95d | 426 | linkage_check_cxx98_cxx11_erase_iterators(_Tp& container) |
427 | { | |
7b96e840 | 428 | // Crashing when external reference and internal reference symbols are |
8544d95d | 429 | // equivalently mangled but have different size return types in C++98 |
430 | // and C++11 signatures. | |
431 | erase_external_iterators(container);// C++98 | |
432 | ||
433 | auto iter = container.begin(); | |
434 | container.erase(iter, ++iter); // C++11 | |
435 | } | |
436 | #endif | |
43308b7e | 437 | |
438 | } // namespace __gnu_test | |
439 | ||
440 | #endif |