| // -*- C++ -*- | 
 |  | 
 | // Copyright (C) 2009-2021 Free Software Foundation, Inc. | 
 | // | 
 | // This file is part of the GNU ISO C++ Library.  This library is free | 
 | // software; you can redistribute it and/or modify it under the terms | 
 | // of the GNU General Public License as published by the Free Software | 
 | // Foundation; either version 3, or (at your option) any later | 
 | // version. | 
 |  | 
 | // This library is distributed in the hope that it will be useful, but | 
 | // WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | // General Public License for more details. | 
 |  | 
 | // You should have received a copy of the GNU General Public License along | 
 | // with this library; see the file COPYING3.  If not see | 
 | // <http://www.gnu.org/licenses/>. | 
 |  | 
 | #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H | 
 | #define _GLIBCXX_TESTSUITE_CONTAINERS_H | 
 |  | 
 | #include <bits/boost_concept_check.h> | 
 | #include <cassert> | 
 | #include <testsuite_container_traits.h> | 
 | #include <utility> // for rel_ops. | 
 |  | 
 | // Container requirement testing. | 
 | namespace __gnu_test | 
 | { | 
 |   // Compile-time typedef testing. | 
 |   template<typename _Tp, bool _Bt = traits<_Tp>::is_container::value> | 
 |     struct basic_types | 
 |     { | 
 |       // Base container requirements (table 80) | 
 |       typedef _Tp 					test_type; | 
 |       typedef typename test_type::value_type 		value_type; | 
 |       typedef typename test_type::pointer 		pointer; | 
 |       typedef typename test_type::const_pointer 	const_pointer; | 
 |       typedef typename test_type::reference 		reference; | 
 |       typedef typename test_type::const_reference 	const_reference; | 
 |       typedef typename test_type::iterator 		iterator; | 
 |       typedef typename test_type::const_iterator 	const_iterator; | 
 |       typedef typename test_type::size_type 		size_type; | 
 |       typedef typename test_type::difference_type 	difference_type; | 
 |     }; | 
 |  | 
 |   // Conditional typedef testing, positive. | 
 |   template<typename _Tp, bool _Bt = traits<_Tp>::is_reversible::value> | 
 |     struct reversible_types | 
 |     { | 
 |       // Reversible container requirements (table 81) | 
 |       typedef _Tp 					 test_type; | 
 |       typedef typename test_type::reverse_iterator 	 reverse_iterator; | 
 |       typedef typename test_type::const_reverse_iterator const_reverse_iterator; | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool _Bt = traits<_Tp>::is_allocator_aware::value> | 
 |     struct allocator_aware_types | 
 |     { | 
 |       // _Alloc-aware requirements (table 82) | 
 |       typedef _Tp 					 test_type; | 
 |       typedef typename test_type::allocator_type      	 allocator_type; | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool _Bt = traits<_Tp>::is_associative::value> | 
 |     struct associative_types | 
 |     { | 
 |       // Associative container requirements (table 85) | 
 |       typedef _Tp 					 test_type; | 
 |       typedef typename test_type::key_type		 key_type; | 
 |       typedef typename test_type::key_compare		 key_compare; | 
 |       typedef typename test_type::value_compare		 value_compare; | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool = traits<_Tp>::is_unordered::value> | 
 |     struct unordered_types | 
 |     { | 
 |       // Unordered associative container requirements (table 87) | 
 |       typedef _Tp 					 test_type; | 
 |       typedef typename test_type::key_type		 key_type; | 
 |       typedef typename test_type::hasher		 hasher; | 
 |       typedef typename test_type::key_equal		 key_equal; | 
 |       typedef typename test_type::local_iterator	 local_iterator; | 
 |       typedef typename test_type::const_local_iterator	 const_local_iterator; | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool _Bt = traits<_Tp>::is_mapped::value> | 
 |     struct mapped_types | 
 |     { | 
 |       typedef _Tp 					 test_type; | 
 |       typedef typename test_type::mapped_type	   	 mapped_type; | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool = traits<_Tp>::is_adaptor::value> | 
 |     struct adaptor_types | 
 |     { | 
 |       // Container adaptor requirements. | 
 |       typedef _Tp 					test_type; | 
 |       typedef typename test_type::value_type 		value_type; | 
 |       typedef typename test_type::reference 		reference; | 
 |       typedef typename test_type::const_reference 	const_reference; | 
 |       typedef typename test_type::size_type 		size_type; | 
 |       typedef typename test_type::container_type 	container_type; | 
 |     }; | 
 |  | 
 |   // Conditional typedef testing, negative. | 
 |   template<typename _Tp> | 
 |     struct basic_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct adaptor_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct reversible_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct allocator_aware_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct associative_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct unordered_types<_Tp, false> { }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct mapped_types<_Tp, false> { }; | 
 |  | 
 |   // Primary template. | 
 |   template<typename _Tp> | 
 |     struct types | 
 |     : basic_types<_Tp>, adaptor_types<_Tp>, reversible_types<_Tp>, | 
 |       allocator_aware_types<_Tp>, associative_types<_Tp>, | 
 |       unordered_types<_Tp>, mapped_types<_Tp> | 
 |     { }; | 
 |  | 
 |  | 
 |   // Run-time test for constant_iterator requirements. | 
 |   template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value> | 
 |     struct populate | 
 |     { | 
 |       populate(_Tp& container) | 
 |       { | 
 | 	// Avoid uninitialized warnings, requires DefaultContructible. | 
 | 	typedef typename _Tp::value_type value_type; | 
 | 	container.insert(container.begin(), value_type()); | 
 | 	container.insert(container.begin(), value_type()); | 
 |       } | 
 |   }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct populate<_Tp, false> | 
 |     { | 
 |       populate(_Tp& container) { } | 
 |     }; | 
 |  | 
 |   template<typename _Tp, bool = traits<_Tp>::is_reversible::value> | 
 |     struct reverse_members | 
 |     { | 
 |       reverse_members(_Tp& container) | 
 |       { | 
 | 	assert( container.crbegin() == container.rbegin() ); | 
 | 	assert( container.crend() == container.rend() ); | 
 | 	assert( container.crbegin() != container.crend() ); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct reverse_members<_Tp, false> | 
 |     { | 
 |       reverse_members(_Tp&) { } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator, | 
 | 	   bool _Mutable, | 
 | 	   typename = typename std::iterator_traits<_Iterator>::iterator_category> | 
 |     struct iterator_concept_checks; | 
 |  | 
 | #if __cplusplus >= 201103L | 
 |   // DR 691. | 
 |   template<typename _Tp> | 
 |     struct forward_members_unordered | 
 |     { | 
 |       forward_members_unordered(const typename _Tp::value_type& v) | 
 |       { | 
 | 	// Make sure that even if rel_ops is injected there is no ambiguity | 
 | 	// when comparing iterators. | 
 | 	using namespace std::rel_ops; | 
 |  | 
 | 	typedef _Tp					test_type; | 
 | 	test_type container; | 
 | 	container.insert(v); | 
 |  | 
 | 	iterator_concept_checks<typename _Tp::local_iterator, false> cc; | 
 | 	iterator_concept_checks<typename _Tp::const_local_iterator, | 
 | 				false> ccc; | 
 |  | 
 | 	assert( container.cbegin(0) == container.begin(0) ); | 
 | 	assert( container.cend(0) == container.end(0) ); | 
 | 	const auto bn = container.bucket(1); | 
 | 	auto clit = container.cbegin(bn); | 
 | 	assert( clit != container.cend(bn) ); | 
 | 	assert( clit != container.end(bn) ); | 
 | 	assert( clit++ == container.cbegin(bn) ); | 
 | 	assert( clit == container.end(bn) ); | 
 |  | 
 | 	clit = container.cbegin(bn); | 
 | 	assert( ++clit == container.cend(bn) ); | 
 |  | 
 | 	assert( container.begin(bn) != container.cend(bn) ); | 
 |       } | 
 |     }; | 
 | #endif | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, false, | 
 | 				   std::forward_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_ForwardIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, true, | 
 | 				   std::forward_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, false, | 
 | 				   std::bidirectional_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_BidirectionalIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, true, | 
 | 				   std::bidirectional_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, false, | 
 | 				   std::random_access_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_RandomAccessIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Iterator> | 
 |     struct iterator_concept_checks<_Iterator, true, | 
 | 				   std::random_access_iterator_tag> | 
 |     { | 
 |       iterator_concept_checks() | 
 |       { | 
 | 	using namespace __gnu_cxx; | 
 | 	__function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>(); | 
 |       } | 
 |     }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct forward_members | 
 |     { | 
 |       forward_members(_Tp& container) | 
 |       { | 
 | 	// Make sure that even if rel_ops is injected there is no ambiguity | 
 | 	// when comparing iterators. | 
 | 	using namespace std::rel_ops; | 
 |  | 
 | 	typedef traits<_Tp> traits_type; | 
 | 	iterator_concept_checks<typename _Tp::iterator, | 
 | 				!(traits_type::is_associative::value | 
 | 				  || traits_type::is_unordered::value)> cc; | 
 | 	iterator_concept_checks<typename _Tp::const_iterator, false> ccc; | 
 |  | 
 | 	assert( container.cbegin() == container.begin() ); | 
 | 	assert( container.end() == container.cend() ); | 
 | 	assert( container.cbegin() != container.cend() ); | 
 | 	assert( container.cbegin() != container.end() ); | 
 | 	assert( container.begin() != container.cend() ); | 
 |       } | 
 |   }; | 
 |  | 
 |   template<typename _Tp, | 
 | 	   typename | 
 |     = typename std::iterator_traits<typename _Tp::iterator>::iterator_category> | 
 |     struct category_members : forward_members<_Tp> | 
 |     { | 
 |       category_members(_Tp& container) | 
 | 	: forward_members<_Tp>(container) | 
 |       { }; | 
 |     }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct category_members<_Tp, std::random_access_iterator_tag> | 
 |     : forward_members<_Tp> | 
 |     { | 
 |       category_members(_Tp& container) | 
 | 	: forward_members<_Tp>(container) | 
 |       { | 
 | 	// Make sure that even if rel_ops is injected there is no ambiguity | 
 | 	// when comparing iterators. | 
 | 	using namespace std::rel_ops; | 
 |  | 
 | 	assert( !(container.begin() < container.begin()) ); | 
 | 	assert( !(container.cbegin() < container.cbegin()) ); | 
 | 	assert( !(container.cbegin() < container.begin()) ); | 
 | 	assert( !(container.begin() < container.cbegin()) ); | 
 | 	assert( container.begin() <= container.begin() ); | 
 | 	assert( container.cbegin() <= container.cbegin() ); | 
 | 	assert( container.cbegin() <= container.begin() ); | 
 | 	assert( container.begin() <= container.cbegin() ); | 
 |  | 
 | 	assert( !(container.begin() > container.begin()) ); | 
 | 	assert( !(container.cbegin() > container.cbegin()) ); | 
 | 	assert( !(container.cbegin() > container.begin()) ); | 
 | 	assert( !(container.begin() > container.cbegin()) ); | 
 | 	assert( container.begin() >= container.begin() ); | 
 | 	assert( container.cbegin() >= container.cbegin() ); | 
 | 	assert( container.cbegin() >= container.begin() ); | 
 | 	assert( container.begin() >= container.cbegin() ); | 
 |  | 
 | 	assert( container.begin() - container.begin() == 0 ); | 
 | 	assert( container.cbegin() - container.cbegin() == 0 ); | 
 | 	assert( container.cbegin() - container.begin() == 0 ); | 
 | 	assert( container.begin() - container.cbegin() == 0 ); | 
 |  | 
 | 	assert( container.begin() + 0 == container.begin() ); | 
 | 	assert( container.cbegin() + 0 == container.cbegin() ); | 
 | 	assert( 0 + container.begin() == container.begin() ); | 
 | 	assert( 0 + container.cbegin() == container.cbegin() ); | 
 | 	assert( container.begin() - 0 == container.begin() ); | 
 | 	assert( container.cbegin() - 0 == container.cbegin() ); | 
 |       } | 
 |   }; | 
 |  | 
 |   template<typename _Tp> | 
 |     struct citerator | 
 |     { | 
 |       typedef _Tp 					test_type; | 
 |       typedef traits<test_type>				traits_type; | 
 |       typedef typename test_type::value_type 		value_type; | 
 |  | 
 |       static test_type _S_container; | 
 |  | 
 |       // Unconditional. | 
 |       struct members : category_members<_Tp> | 
 |       { | 
 | 	members() : category_members<_Tp>(_S_container) | 
 | 	{ } | 
 |       }; | 
 |  | 
 |       // Run test. | 
 |       citerator() | 
 |       { | 
 | 	populate<test_type> p(_S_container); | 
 | 	members m1; | 
 | 	reverse_members<test_type> m2(_S_container); | 
 |       } | 
 |   }; | 
 |  | 
 |   template<typename _Tp> | 
 |   _Tp citerator<_Tp>::_S_container; | 
 |  | 
 |   // DR 130 vs. C++98 vs. C++11. | 
 |   // Defined in testsuite_shared.cc. | 
 |   void | 
 |   erase_external(std::set<int>& s); | 
 |  | 
 |   void | 
 |   erase_external(std::multiset<int>& s); | 
 |  | 
 |   void | 
 |   erase_external(std::map<int, int>& s); | 
 |  | 
 |   void | 
 |   erase_external(std::multimap<int, int>& s); | 
 |  | 
 |   void | 
 |   erase_external_iterators(std::set<int>& s); | 
 |  | 
 |   void | 
 |   erase_external_iterators(std::multiset<int>& s); | 
 |  | 
 |   void | 
 |   erase_external_iterators(std::map<int, int>& s); | 
 |  | 
 |   void | 
 |   erase_external_iterators(std::multimap<int, int>& s); | 
 |  | 
 | #if __cplusplus < 201103L | 
 | # error "must be compiled with C++11 (or later)" | 
 | #else | 
 | template<typename _Tp> | 
 |   void | 
 |   linkage_check_cxx98_cxx11_erase(_Tp& container) | 
 |   { | 
 |     // Crashing when external reference and internal reference symbols are | 
 |     // equivalently mangled but have different size return types in C++98 | 
 |     // and C++11 signatures. | 
 |     erase_external(container); 		// C++98 | 
 |     container.erase(container.begin());	// C++11 | 
 |   } | 
 |  | 
 | template<typename _Tp> | 
 |   void | 
 |   linkage_check_cxx98_cxx11_erase_iterators(_Tp& container) | 
 |   { | 
 |     // Crashing when external reference and internal reference symbols are | 
 |     // equivalently mangled but have different size return types in C++98 | 
 |     // and C++11 signatures. | 
 |     erase_external_iterators(container);// C++98 | 
 |  | 
 |     auto iter = container.begin(); | 
 |     container.erase(iter, ++iter);	// C++11 | 
 |   } | 
 | #endif | 
 |  | 
 | } // namespace __gnu_test | 
 |  | 
 | #endif |