| /*************************************************************************** |
| * |
| * 20.operators.cpp - test exercising [lib.operators] |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * 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 <rw/_config.h> |
| |
| #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 <algorithm> |
| #include <deque> |
| #include <functional> |
| #include <iterator> |
| #include <list> |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| #include <utility> |
| #include <cstddef> // for std::size_t |
| |
| #include <driver.h> |
| |
| /**************************************************************************/ |
| |
| _USING (namespace std); |
| _USING (namespace std::rel_ops); |
| |
| |
| #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION |
| |
| // explicitly instantiate containers |
| template class |
| std::deque<int, std::allocator<int> >; |
| |
| template class |
| std::list<int,std::allocator<int> >; |
| |
| template class |
| std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >; |
| |
| template class |
| std::set<int>; |
| |
| template class |
| std::basic_string<int, std::char_traits<int>, std::allocator<int> >; |
| |
| template class |
| std::vector<int, std::allocator<int> >; |
| |
| #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 <class Container, class RandomAccessIterator> |
| void test_iterator (Container, RandomAccessIterator) |
| { |
| TEST_OPERATORS (typename Container); |
| } |
| |
| |
| template <class Container> |
| void test_iterator (Container, int*) |
| { |
| // cannot specialize std::rel_ops::operators on native types |
| // or pointers to such things |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T> |
| struct UnaryPredicate |
| { |
| bool operator() (const T&) const { |
| return true; |
| } |
| }; |
| |
| |
| template <class T> |
| struct BinaryPredicate |
| { |
| bool operator() (const T&, const T&) const { |
| return true; |
| } |
| }; |
| |
| |
| template <class T> |
| struct RandomNumberGenerator |
| { |
| T operator() (int) const { |
| return T (); |
| } |
| }; |
| |
| |
| template <class T> |
| struct Generator |
| { |
| T operator() () const { |
| return T (); |
| } |
| }; |
| |
| template <class T> |
| struct UnaryFunction |
| { |
| T operator() (const T &t) const { |
| return t; |
| } |
| }; |
| |
| |
| template <class T> |
| struct BinaryFunction |
| { |
| T operator() (const T &t, const T&) const { |
| return t; |
| } |
| }; |
| |
| /**************************************************************************/ |
| |
| template <class T, class InputIterator> |
| 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<T>()); |
| std::find (I (), I (), T ()); |
| std::find_if (I (), I (), UnaryPredicate<T>()); |
| |
| #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC |
| std::count (I (), I (), T ()); |
| std::count_if (I (), I (), UnaryPredicate<T>()); |
| #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<T>(), n); |
| #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC |
| |
| std::mismatch (I (), I (), I ()); |
| std::mismatch (I (), I (), I (), BinaryPredicate<T>()); |
| std::equal (I (), I (), I ()); |
| std::equal (I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::includes (I (), I (), I (), I ()); |
| std::includes (I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::lexicographical_compare (I (), I (), I (), I ()); |
| std::lexicographical_compare (I (), I (), I (), I (), BinaryPredicate<T>()); |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T, class OutputIterator> |
| 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<T>()); |
| std::transform (I (), I (), I (), I (), BinaryFunction<T>()); |
| |
| std::replace_copy (I (), I (), I (), T (), T ()); |
| std::replace_copy_if (I (), I (), I (), UnaryPredicate<T>(), T ()); |
| |
| std::merge (I (), I (), I (), I (), I ()); |
| std::merge (I (), I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::set_union (I (), I (), I (), I (), I ()); |
| std::set_union (I (), I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::set_intersection (I (), I (), I (), I (), I ()); |
| std::set_intersection (I (), I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::set_difference (I (), I (), I (), I (), I ()); |
| std::set_difference (I (), I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::set_symmetric_difference (I (), I (), I (), I (), I ()); |
| std::set_symmetric_difference (I (), I (), I (), I (), I (), |
| BinaryPredicate<T>()); |
| |
| std::fill_n (I (), 0, T ()); |
| |
| std::generate_n (I (), 0, Generator<T>()); |
| |
| std::remove_copy (I (), I (), I (), T ()); |
| std::remove_copy_if (I (), I (), I (), UnaryPredicate<T>()); |
| |
| std::unique_copy (I (), I (), I ()); |
| std::unique_copy (I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::reverse_copy (I (), I (), I ()); |
| |
| std::rotate_copy (I (), I (), I (), I ()); |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T, class ForwardIterator> |
| 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<T>()); |
| |
| std::find_first_of (I (), I (), I (), I ()); |
| std::find_first_of (I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::adjacent_find (I (), I ()); |
| std::adjacent_find (I (), I (), BinaryPredicate<T>()); |
| |
| std::search (I (), I (), I (), I ()); |
| std::search (I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::search_n (I (), I (), 0, T ()); |
| std::search_n (I (), I (), 0, T (), BinaryPredicate<T>()); |
| |
| std::swap_ranges (I (), I (), I ()); |
| std::iter_swap (I (), I ()); |
| |
| std::replace (I (), I (), T (), T ()); |
| std::replace_if (I (), I (), UnaryPredicate<T>(), T ()); |
| |
| std::equal_range (I (), I (), T ()); |
| std::equal_range (I (), I (), T (), BinaryPredicate<T>()); |
| |
| std::binary_search (I (), I (), T ()); |
| std::binary_search (I (), I (), T (), BinaryPredicate<T>()); |
| |
| std::min_element (I (), I ()); |
| std::min_element (I (), I (), BinaryPredicate<T>()); |
| |
| std::max_element (I (), I ()); |
| std::max_element (I (), I (), BinaryPredicate<T>()); |
| |
| std::fill (I (), I (), T ()); |
| |
| std::generate (I (), I (), Generator<T>()); |
| |
| std::remove (I (), I (), T ()); |
| std::remove_if (I (), I (), UnaryPredicate<T>()); |
| |
| std::unique (I (), I ()); |
| std::unique (I (), I (), BinaryPredicate<T>()); |
| |
| std::reverse (I (), I ()); |
| |
| std::rotate (I (), I (), I ()); |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T, class BidirectionalIterator> |
| 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<T>()); |
| std::stable_partition (I (), I (), UnaryPredicate<T>()); |
| |
| std::lower_bound (I (), I (), T ()); |
| std::lower_bound (I (), I (), T (), BinaryPredicate<T>()); |
| |
| std::upper_bound (I (), I (), T ()); |
| std::upper_bound (I (), I (), T (), BinaryPredicate<T>()); |
| |
| std::inplace_merge (I (), I (), I ()); |
| std::inplace_merge (I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::next_permutation (I (), I ()); |
| std::next_permutation (I (), I (), BinaryPredicate<T>()); |
| |
| std::prev_permutation (I (), I ()); |
| std::prev_permutation (I (), I (), BinaryPredicate<T>()); |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T, class RandomAccessIterator> |
| 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<T> rndgen; |
| |
| std::random_shuffle (I (), I ()); |
| std::random_shuffle (I (), I (), rndgen); |
| |
| std::sort (I (), I ()); |
| std::sort (I (), I (), BinaryPredicate<T>()); |
| |
| std::stable_sort (I (), I ()); |
| std::stable_sort (I (), I (), BinaryPredicate<T>()); |
| |
| std::partial_sort (I (), I (), I ()); |
| std::partial_sort (I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::partial_sort_copy (I (), I (), I (), I ()); |
| std::partial_sort_copy (I (), I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::nth_element (I (), I (), I ()); |
| std::nth_element (I (), I (), I (), BinaryPredicate<T>()); |
| |
| std::push_heap (I (), I (), BinaryPredicate<T>()); |
| std::pop_heap (I (), I (), BinaryPredicate<T>()); |
| std::make_heap (I (), I (), BinaryPredicate<T>()); |
| std::sort_heap (I (), I (), BinaryPredicate<T>()); |
| } |
| |
| /**************************************************************************/ |
| |
| static int |
| run_test (int, char**) |
| { |
| typedef std::map<int, int> Map; |
| typedef std::multimap<int, int> MultiMap; |
| |
| // verify that rel_ops operators can be instantiated |
| // on iterators of the containers below |
| TEST_OPERATORS (std::deque<int>); |
| |
| TEST_INEQUALITY (std::list<int>); |
| TEST_INEQUALITY (Map); |
| TEST_INEQUALITY (MultiMap); |
| TEST_INEQUALITY (std::set<int>); |
| TEST_INEQUALITY (std::multiset<int>); |
| |
| #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<int>(), |
| std::basic_string<int>::iterator ()); |
| |
| test_iterator (std::vector<int>(), |
| std::vector<int>::iterator ()); |
| #endif // MSVC > 7.0 |
| |
| TEST_OPERATORS (std::vector<bool>); |
| |
| #define TEST_INPUT_ITERATORS(T) \ |
| test_input_iterators (T (), std::deque<T>::iterator ()); \ |
| test_input_iterators (T (), std::list<T>::iterator ()); \ |
| test_input_iterators (std::map<T, T>::value_type (), \ |
| std::map<T, T>::iterator ()); \ |
| test_input_iterators (std::multimap<T, T>::value_type (), \ |
| std::multimap<T, T>::iterator ()); \ |
| test_input_iterators (T (), std::set<T>::iterator ()); \ |
| test_input_iterators (T (), std::multiset<T, T>::iterator ()); \ |
| test_input_iterators (T (), std::basic_string<T>::iterator ()); \ |
| test_input_iterators (T (), std::vector<T>::iterator ()) |
| |
| #define TEST_OUTPUT_ITERATORS(T) \ |
| test_output_iterators (T (), std::deque<T>::iterator ()); \ |
| test_output_iterators (T (), std::list<T>::iterator ()); \ |
| test_output_iterators (T (), std::basic_string<T>::iterator ()); \ |
| test_output_iterators (T (), std::vector<T>::iterator ()) |
| |
| #define TEST_FORWARD_ITERATORS(T) \ |
| test_forward_iterators (T (), std::deque<T>::iterator ()); \ |
| test_forward_iterators (T (), std::list<T>::iterator ()); \ |
| test_forward_iterators (T (), std::basic_string<T>::iterator ()); \ |
| test_forward_iterators (T (), std::vector<T>::iterator ()) |
| |
| #define TEST_BIDIRECTIONAL_ITERATORS(T) \ |
| test_bidirectional_iterators (T (), std::deque<T>::iterator ()); \ |
| test_bidirectional_iterators (T (), std::list<T>::iterator ()); \ |
| test_bidirectional_iterators (T (), std::basic_string<T>::iterator ()); \ |
| test_bidirectional_iterators (T (), std::vector<T>::iterator ()) |
| |
| #define TEST_RANDOM_ACCESS_ITERATORS(T) \ |
| test_random_access_iterators (T (), std::deque<T>::iterator ()); \ |
| test_random_access_iterators (T (), std::basic_string<T>::iterator ()); \ |
| test_random_access_iterators (T (), std::vector<T>::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 */); |
| } |