/*************************************************************************** * * 20.operators.cpp - test exercising [lib.operators] * * $Id: 20.operators.cpp 448928 2006-09-22 13:43:18Z faridz $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Copyright 1994-2006 Rogue Wave Software. * **************************************************************************/ // The test exercises the ability to specialize various components of // the library (algorithms and containers in particular) on user-defined // iterator types in the presence of using directives. #include #if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION) // Disable implicit inclusion to work around // a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959) # define _RWSTD_NO_IMPLICIT_INCLUSION #endif #if 0 // def _MSC_VER // disabled (warnings may be meaningful) # pragma warning (disable: 4800) # pragma warning (disable: 4805) #endif // _MSC_VER #include #include #include #include #include #include #include #include #include #include #include // for std::size_t #include /**************************************************************************/ _USING (namespace std); _USING (namespace std::rel_ops); #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION // explicitly instantiate containers template class std::deque >; template class std::list >; template class std::map, std::allocator > >; template class std::set; template class std::basic_string, std::allocator >; template class std::vector >; #endif // _RWSTD_NO_EXPLICIT_INSTANTIATION /**************************************************************************/ #if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x530 # define FUN(ignore, result, name, arg_list) do { \ result (*pf) arg_list = &name; \ _RWSTD_UNUSED (pf); \ } while (0) #else // working around a SunPro 5.3 bug (see PR #25972) that prevents it // from taking the address of a function template in template code # define FUN(T, result, name, arg_list) do { \ typedef typename T::iterator Iterator; \ typedef typename T::const_iterator ConstIterator; \ const Iterator *pi = 0; \ const ConstIterator *pci = 0; \ name (pi, pi); \ name (pci, pci); \ } while (0) #endif // SunPro 5.3 #define TEST_INEQUALITY(T) \ FUN (T, bool, std::rel_ops::operator!=, \ (const T::iterator&, const T::iterator&)); \ FUN (T, bool, std::rel_ops::operator!=, \ (const T::const_iterator&, const T::const_iterator&)) #define TEST_OPERATORS(T) \ TEST_INEQUALITY (T); \ FUN (T, bool, std::rel_ops::operator>, \ (const T::iterator&, const T::iterator&)); \ FUN (T, bool, std::rel_ops::operator<=, \ (const T::iterator&, const T::iterator&)); \ FUN (T, bool, std::rel_ops::operator>=, \ (const T::iterator&, const T::iterator&)); \ FUN (T, bool, std::rel_ops::operator>, \ (const T::const_iterator&, const T::const_iterator&)); \ FUN (T, bool, std::rel_ops::operator<=, \ (const T::const_iterator&, const T::const_iterator&)); \ FUN (T, bool, std::rel_ops::operator>=, \ (const T::const_iterator&, const T::const_iterator&)) template void test_iterator (Container, RandomAccessIterator) { TEST_OPERATORS (typename Container); } template void test_iterator (Container, int*) { // cannot specialize std::rel_ops::operators on native types // or pointers to such things } /**************************************************************************/ template struct UnaryPredicate { bool operator() (const T&) const { return true; } }; template struct BinaryPredicate { bool operator() (const T&, const T&) const { return true; } }; template struct RandomNumberGenerator { T operator() (int) const { return T (); } }; template struct Generator { T operator() () const { return T (); } }; template struct UnaryFunction { T operator() (const T &t) const { return t; } }; template struct BinaryFunction { T operator() (const T &t, const T&) const { return t; } }; /**************************************************************************/ template void test_input_iterators (T, InputIterator) { // do not run (compile only), prevent warnings about unreachable code static int count = 0; if (++count) return; typedef InputIterator I; std::for_each (I (), I (), UnaryFunction()); std::find (I (), I (), T ()); std::find_if (I (), I (), UnaryPredicate()); #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC std::count (I (), I (), T ()); std::count_if (I (), I (), UnaryPredicate()); #else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) std::size_t n = 0; std::count (I (), I (), T (), n); std::count_if (I (), I (), UnaryPredicate(), n); #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC std::mismatch (I (), I (), I ()); std::mismatch (I (), I (), I (), BinaryPredicate()); std::equal (I (), I (), I ()); std::equal (I (), I (), I (), BinaryPredicate()); std::includes (I (), I (), I (), I ()); std::includes (I (), I (), I (), I (), BinaryPredicate()); std::lexicographical_compare (I (), I (), I (), I ()); std::lexicographical_compare (I (), I (), I (), I (), BinaryPredicate()); } /**************************************************************************/ template void test_output_iterators (T, OutputIterator) { // do not run (compile only), prevent warnings about unreachable code static int count = 0; if (++count) return; typedef OutputIterator I; std::copy (I (), I (), I ()); std::copy_backward (I (), I (), I ()); std::transform (I (), I (), I (), UnaryFunction()); std::transform (I (), I (), I (), I (), BinaryFunction()); std::replace_copy (I (), I (), I (), T (), T ()); std::replace_copy_if (I (), I (), I (), UnaryPredicate(), T ()); std::merge (I (), I (), I (), I (), I ()); std::merge (I (), I (), I (), I (), I (), BinaryPredicate()); std::set_union (I (), I (), I (), I (), I ()); std::set_union (I (), I (), I (), I (), I (), BinaryPredicate()); std::set_intersection (I (), I (), I (), I (), I ()); std::set_intersection (I (), I (), I (), I (), I (), BinaryPredicate()); std::set_difference (I (), I (), I (), I (), I ()); std::set_difference (I (), I (), I (), I (), I (), BinaryPredicate()); std::set_symmetric_difference (I (), I (), I (), I (), I ()); std::set_symmetric_difference (I (), I (), I (), I (), I (), BinaryPredicate()); std::fill_n (I (), 0, T ()); std::generate_n (I (), 0, Generator()); std::remove_copy (I (), I (), I (), T ()); std::remove_copy_if (I (), I (), I (), UnaryPredicate()); std::unique_copy (I (), I (), I ()); std::unique_copy (I (), I (), I (), BinaryPredicate()); std::reverse_copy (I (), I (), I ()); std::rotate_copy (I (), I (), I (), I ()); } /**************************************************************************/ template void test_forward_iterators (T, ForwardIterator) { // do not run (compile only), prevent warnings about unreachable code static int count = 0; if (++count) return; typedef ForwardIterator I; std::find_end (I (), I (), I (), I ()); std::find_end (I (), I (), I (), I (), BinaryPredicate()); std::find_first_of (I (), I (), I (), I ()); std::find_first_of (I (), I (), I (), I (), BinaryPredicate()); std::adjacent_find (I (), I ()); std::adjacent_find (I (), I (), BinaryPredicate()); std::search (I (), I (), I (), I ()); std::search (I (), I (), I (), I (), BinaryPredicate()); std::search_n (I (), I (), 0, T ()); std::search_n (I (), I (), 0, T (), BinaryPredicate()); std::swap_ranges (I (), I (), I ()); std::iter_swap (I (), I ()); std::replace (I (), I (), T (), T ()); std::replace_if (I (), I (), UnaryPredicate(), T ()); std::equal_range (I (), I (), T ()); std::equal_range (I (), I (), T (), BinaryPredicate()); std::binary_search (I (), I (), T ()); std::binary_search (I (), I (), T (), BinaryPredicate()); std::min_element (I (), I ()); std::min_element (I (), I (), BinaryPredicate()); std::max_element (I (), I ()); std::max_element (I (), I (), BinaryPredicate()); std::fill (I (), I (), T ()); std::generate (I (), I (), Generator()); std::remove (I (), I (), T ()); std::remove_if (I (), I (), UnaryPredicate()); std::unique (I (), I ()); std::unique (I (), I (), BinaryPredicate()); std::reverse (I (), I ()); std::rotate (I (), I (), I ()); } /**************************************************************************/ template void test_bidirectional_iterators (T, BidirectionalIterator) { // do not run (compile only), prevent warnings about unreachable code static int count = 0; if (++count) return; typedef BidirectionalIterator I; std::partition (I (), I (), UnaryPredicate()); std::stable_partition (I (), I (), UnaryPredicate()); std::lower_bound (I (), I (), T ()); std::lower_bound (I (), I (), T (), BinaryPredicate()); std::upper_bound (I (), I (), T ()); std::upper_bound (I (), I (), T (), BinaryPredicate()); std::inplace_merge (I (), I (), I ()); std::inplace_merge (I (), I (), I (), BinaryPredicate()); std::next_permutation (I (), I ()); std::next_permutation (I (), I (), BinaryPredicate()); std::prev_permutation (I (), I ()); std::prev_permutation (I (), I (), BinaryPredicate()); } /**************************************************************************/ template void test_random_access_iterators (T, RandomAccessIterator) { // do not run (compile only), prevent warnings about unreachable code static int count = 0; if (++count) return; typedef RandomAccessIterator I; RandomNumberGenerator rndgen; std::random_shuffle (I (), I ()); std::random_shuffle (I (), I (), rndgen); std::sort (I (), I ()); std::sort (I (), I (), BinaryPredicate()); std::stable_sort (I (), I ()); std::stable_sort (I (), I (), BinaryPredicate()); std::partial_sort (I (), I (), I ()); std::partial_sort (I (), I (), I (), BinaryPredicate()); std::partial_sort_copy (I (), I (), I (), I ()); std::partial_sort_copy (I (), I (), I (), I (), BinaryPredicate()); std::nth_element (I (), I (), I ()); std::nth_element (I (), I (), I (), BinaryPredicate()); std::push_heap (I (), I (), BinaryPredicate()); std::pop_heap (I (), I (), BinaryPredicate()); std::make_heap (I (), I (), BinaryPredicate()); std::sort_heap (I (), I (), BinaryPredicate()); } /**************************************************************************/ static int run_test (int, char**) { typedef std::map Map; typedef std::multimap MultiMap; // verify that rel_ops operators can be instantiated // on iterators of the containers below TEST_OPERATORS (std::deque); TEST_INEQUALITY (std::list); TEST_INEQUALITY (Map); TEST_INEQUALITY (MultiMap); TEST_INEQUALITY (std::set); TEST_INEQUALITY (std::multiset); #if !defined (_MSC_VER) || _MSC_VER > 1300 // prevent from testing with the braindead MSVC 6 and 7 // as a workaround for compiler bugs (PR #16828, 22268) // prevent attempts to specialize rel_ops operators on // native types (or pointers to such things) test_iterator (std::basic_string(), std::basic_string::iterator ()); test_iterator (std::vector(), std::vector::iterator ()); #endif // MSVC > 7.0 TEST_OPERATORS (std::vector); #define TEST_INPUT_ITERATORS(T) \ test_input_iterators (T (), std::deque::iterator ()); \ test_input_iterators (T (), std::list::iterator ()); \ test_input_iterators (std::map::value_type (), \ std::map::iterator ()); \ test_input_iterators (std::multimap::value_type (), \ std::multimap::iterator ()); \ test_input_iterators (T (), std::set::iterator ()); \ test_input_iterators (T (), std::multiset::iterator ()); \ test_input_iterators (T (), std::basic_string::iterator ()); \ test_input_iterators (T (), std::vector::iterator ()) #define TEST_OUTPUT_ITERATORS(T) \ test_output_iterators (T (), std::deque::iterator ()); \ test_output_iterators (T (), std::list::iterator ()); \ test_output_iterators (T (), std::basic_string::iterator ()); \ test_output_iterators (T (), std::vector::iterator ()) #define TEST_FORWARD_ITERATORS(T) \ test_forward_iterators (T (), std::deque::iterator ()); \ test_forward_iterators (T (), std::list::iterator ()); \ test_forward_iterators (T (), std::basic_string::iterator ()); \ test_forward_iterators (T (), std::vector::iterator ()) #define TEST_BIDIRECTIONAL_ITERATORS(T) \ test_bidirectional_iterators (T (), std::deque::iterator ()); \ test_bidirectional_iterators (T (), std::list::iterator ()); \ test_bidirectional_iterators (T (), std::basic_string::iterator ()); \ test_bidirectional_iterators (T (), std::vector::iterator ()) #define TEST_RANDOM_ACCESS_ITERATORS(T) \ test_random_access_iterators (T (), std::deque::iterator ()); \ test_random_access_iterators (T (), std::basic_string::iterator ()); \ test_random_access_iterators (T (), std::vector::iterator ()); \ // verify that algorithms can be specialized on container // iterators without causing ambiguities with rel_ops TEST_INPUT_ITERATORS (int); TEST_OUTPUT_ITERATORS (int); TEST_FORWARD_ITERATORS (int); TEST_BIDIRECTIONAL_ITERATORS (int); TEST_RANDOM_ACCESS_ITERATORS (int); #if !defined (__HP_aCC) || _RWSTD_HP_aCC_MINOR > 3600 // working around an HP aCC bug (PR #28331) TEST_INPUT_ITERATORS (bool); TEST_OUTPUT_ITERATORS (bool); TEST_FORWARD_ITERATORS (bool); TEST_BIDIRECTIONAL_ITERATORS (bool); TEST_RANDOM_ACCESS_ITERATORS (bool); #endif // HP aCC > x.36 return 0; } /**************************************************************************/ int main (int argc, char *argv[]) { return rw_test (argc, argv, __FILE__, "lib.operators", "interactions with the rest of the implementation", run_test, 0 /* no command line options */); }