// -*- C++ -*- // Copyright (C) 2009-2022 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 // . #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H #define _GLIBCXX_TESTSUITE_CONTAINERS_H #include #include #include #include // for rel_ops. // Container requirement testing. namespace __gnu_test { // Compile-time typedef testing. template::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::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::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::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::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::is_mapped::value> struct mapped_types { typedef _Tp test_type; typedef typename test_type::mapped_type mapped_type; }; template::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 struct basic_types<_Tp, false> { }; template struct adaptor_types<_Tp, false> { }; template struct reversible_types<_Tp, false> { }; template struct allocator_aware_types<_Tp, false> { }; template struct associative_types<_Tp, false> { }; template struct unordered_types<_Tp, false> { }; template struct mapped_types<_Tp, false> { }; // Primary template. template 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::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 struct populate<_Tp, false> { populate(_Tp& container) { } }; template::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 struct reverse_members<_Tp, false> { reverse_members(_Tp&) { } }; template::iterator_category> struct iterator_concept_checks; #if __cplusplus >= 201103L // DR 691. template 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 cc; iterator_concept_checks 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 struct iterator_concept_checks<_Iterator, false, std::forward_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_ForwardIteratorConcept<_Iterator>>(); } }; template struct iterator_concept_checks<_Iterator, true, std::forward_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>(); } }; template struct iterator_concept_checks<_Iterator, false, std::bidirectional_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_BidirectionalIteratorConcept<_Iterator>>(); } }; template struct iterator_concept_checks<_Iterator, true, std::bidirectional_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>(); } }; template struct iterator_concept_checks<_Iterator, false, std::random_access_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_RandomAccessIteratorConcept<_Iterator>>(); } }; template struct iterator_concept_checks<_Iterator, true, std::random_access_iterator_tag> { iterator_concept_checks() { using namespace __gnu_cxx; __function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>(); } }; template 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 cc; iterator_concept_checks 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::iterator_category> struct category_members : forward_members<_Tp> { category_members(_Tp& container) : forward_members<_Tp>(container) { }; }; template 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 struct citerator { typedef _Tp test_type; typedef traits 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 p(_S_container); members m1; reverse_members m2(_S_container); } }; template _Tp citerator<_Tp>::_S_container; // DR 130 vs. C++98 vs. C++11. // Defined in testsuite_shared.cc. void erase_external(std::set& s); void erase_external(std::multiset& s); void erase_external(std::map& s); void erase_external(std::multimap& s); void erase_external_iterators(std::set& s); void erase_external_iterators(std::multiset& s); void erase_external_iterators(std::map& s); void erase_external_iterators(std::multimap& s); #if __cplusplus < 201103L # error "must be compiled with C++11 (or later)" #else template 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 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