testsuite_containers.h 13 KB

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