blob: b93069a96898013380a523fd4ef2f68846842838 [file] [log] [blame]
/***************************************************************************
*
* 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 <rw_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() (T) 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;
#if !defined _RWSTD_NO_DEBUG_ITER
RandomNumberGenerator<typename I::difference_type> rndgen;
#else
RandomNumberGenerator<T> rndgen;
#endif
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 */);
}