526 lines
17 KiB
C++
526 lines
17 KiB
C++
/***************************************************************************
|
|
*
|
|
* 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 <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 */);
|
|
}
|