first commit

This commit is contained in:
Jose Caban
2025-06-07 11:34:38 -04:00
commit 0eb2d7c07d
4708 changed files with 1500614 additions and 0 deletions

View File

@@ -0,0 +1,294 @@
/***************************************************************************
*
* 25.adjacent.find.cpp - test exercising lib.alg.adjacent.find
*
* $Id: 25.adjacent.find.cpp 510071 2007-02-21 15:58:53Z 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 2004-2006 Rogue Wave Software.
*
**************************************************************************/
#include <algorithm> // for adjacent_find()
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h>
/**************************************************************************/
// used to initialize an array of objects of type UserClass
static const char *xinit_begin;
int xinit ()
{
typedef unsigned char UChar;
static const char *cur = 0;
if (!cur || !*cur)
cur = xinit_begin;
return UChar (*cur++);
}
/**************************************************************************/
template <class T, class U>
struct EqualityPredicate
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class
// from being default constructible
EqualityPredicate (T* /* dummy */, U* /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
ConvertibleToBool operator() (const T &x, const U &y) /* non-const */ {
++funcalls_;
return x == y;
}
};
template <class T, class U>
std::size_t EqualityPredicate<T, U>::funcalls_;
/**************************************************************************/
// exercises std::adjacent_find()
template <class ForwardIterator, class T>
void do_test (int line, // line number of test case
const char *src, // source sequence
std::size_t resoff, // offset of result
ForwardIterator dummy_iter,
const T*,
const char* predname)
{
static const char* const itname = type_name (dummy_iter, (T*)0);
const std::size_t nsrc = std::strlen (src);
if (std::size_t (-1) == resoff)
resoff = nsrc;
// have the UserClass default ctor initialize objects from `src'
xinit_begin = src;
UserClass::gen_ = xinit;
UserClass* const xsrc = new UserClass [nsrc];
const ForwardIterator first =
make_iter (xsrc, xsrc, xsrc + nsrc, dummy_iter);
const ForwardIterator last =
make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, dummy_iter);
// reset predicate counters
UserClass::n_total_op_eq_ = 0;
EqualityPredicate<T, T>::funcalls_ = 0;
// construct a predicate object
const EqualityPredicate<T, T> pred (0, 0);
const ForwardIterator res = predname ?
std::adjacent_find (first, last, pred)
: std::adjacent_find (first, last);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (res);
const std::size_t n_total_pred = predname ?
EqualityPredicate<T, T>::funcalls_
: UserClass::n_total_op_eq_;
// verify that the returned iterator is set as expected
int success = res.cur_ == first.cur_ + resoff;
rw_assert (success, 0, line,
"line %d: adjacent_find<%s>(it = \"%s\", ...)"
" == (it + %zu), got (it + %td)",
__LINE__, itname, src,
resoff, res.cur_ - first.cur_);
// verify the number of applications of the predicate (lwg issue 240):
// Complexity: For a nonempty range, exactly
// min((i - first) + 1, (last - first) - 1)
// applications of the corresponding predicate, where i is
// adjacent_find's return value.
// compute the expected number of invocations of the predicate
std::size_t n_expect_pred = 0;
if (nsrc) {
// test iterators are guaranteed to be in range
_RWSTD_ASSERT (first.cur_ <= res.cur_ && res.cur_ <= last.cur_);
n_expect_pred = std::size_t (res.cur_ - first.cur_) + 1;
const std::size_t tmp = std::size_t (last.cur_ - first.cur_) - 1;
if (tmp < n_expect_pred)
n_expect_pred = tmp;
}
success = std::size_t (n_expect_pred) == n_total_pred;
rw_assert (success, 0, line,
"line %d: adjacent_find<%s>(\"%s\", ...) "
"invoked %s %zu times, expected %td",
__LINE__, itname, src,
predname ? predname : "operator==()",
n_total_pred, n_expect_pred);
}
/**************************************************************************/
template <class ForwardIterator, class T>
void run_tests (ForwardIterator dummy_iter, const T*, const char* predname)
{
static const char* const itname = type_name (dummy_iter, (T*)0);
rw_info (0, 0, 0, "std::adjacent_find (%s, %1$s%{?}, %s%{;})",
itname, 0 != predname, predname);
#define TEST(src, off) \
do_test (__LINE__, src, std::size_t (off), dummy_iter, \
(UserClass*)0, predname)
// +------------------ subject sequence
// | +-- offset of returned iterator,
// | | -1 denotes the end of sequence
// v v
TEST ("", -1);
TEST ("a", -1);
TEST ("ab", -1);
TEST ("abc", -1);
TEST ("abcd", -1);
TEST ("abcde", -1);
TEST ("abcdef", -1);
TEST ("abcdefg", -1);
TEST ("abcdefgh", -1);
TEST ("abcdefghi", -1);
TEST ("abcdefghij", -1);
TEST ("abcdefghijk", -1);
TEST ("aabcdefghij", 0);
TEST ("abbcdefghij", 1);
TEST ("abccdefghij", 2);
TEST ("abcddefghij", 3);
TEST ("abcdeefghij", 4);
TEST ("abcdeffghij", 5);
TEST ("abcdefgghij", 6);
TEST ("abcdefghhij", 7);
TEST ("abcdefghiij", 8);
TEST ("abcdefghijj", 9);
TEST ("aaabcdefghi", 0);
TEST ("abbbcdefghi", 1);
TEST ("abcccdefghi", 2);
TEST ("abcdddefghi", 3);
TEST ("abcdeeefghi", 4);
TEST ("abcdefffghi", 5);
TEST ("abcdefggghi", 6);
TEST ("abcdefghhhi", 7);
TEST ("abcdefghiii", 8);
TEST ("abcdefghijjj", 9);
}
/**************************************************************************/
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
static
void test_adjacent_find (const char* predname)
{
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}> "
"%1$s std::adjacent_find (%1$s, %1$s%{?}, %3$s%{;})",
"ForwardIterator", 0 != predname, "BinaryPredicate",
0 != predname);
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
run_tests (FwdIter<UserClass>(), (UserClass*)0, predname);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
run_tests (BidirIter<UserClass>(), (UserClass*)0, predname);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
run_tests (RandomAccessIter<UserClass>(), (UserClass*)0, predname);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_adjacent_find (0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
test_adjacent_find ("EqualityPredicate<UserClass, UserClass>");
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.adjacent.find",
0 /* no comment */, run_test,
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate#",
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,331 @@
/***************************************************************************
*
* 25.binary.search.cpp - test exercising 25.3.4 [lib.binary.search]
*
* $Id: 25.binary.search.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <rw/_config.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// disable implicit inclusion to work around a limitation
// of IBM VisualAge 5.0 (see PR #26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#include <algorithm> // for binary_search()
#include <cstring> // for strlen()
#include <alg_test.h> // for iterators
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test(), ...
/**************************************************************************/
// meets requirements listed at 25.3, p2
template <class T>
struct compare {
bool operator() (const T &a, const T &b) const {
_RWSTD_UNUSED (a);
_RWSTD_UNUSED (b);
return true;
}
};
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
bool
binary_search (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
const lt_comp<assign<base<cpy_ctor> > >&);
template
bool
binary_search (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
const lt_comp<assign<base<cpy_ctor> > >&,
compare<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// distinct and not Less-Than-Comparable with class T (except as
// defined below) to detect unwarranted assumptions made by the
// implementation of the algorithms
struct Y
{
UserClass xval_;
// not Default-Constructible
Y (int /* dummy */, int /*dummy */): xval_ () { }
// CopyConstructible
Y (const Y &rhs): xval_ (rhs.xval_) { }
private:
void operator=(Y&); // not Assignable
};
inline bool
operator< (const UserClass &lhs, const Y &rhs)
{
return lhs < rhs.xval_;
}
inline bool
operator< (const Y &lhs, const UserClass &rhs)
{
return lhs.xval_ < rhs;
}
// predicate used as the Compare argument to upper_bound()
struct LessThan
{
static std::size_t funcalls_;
LessThan (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
bool operator() (const UserClass &lhs, const Y &rhs) {
++funcalls_;
return lhs < rhs.xval_;
}
bool operator() (const Y &lhs, const UserClass &rhs) {
++funcalls_;
return lhs.xval_ < rhs;
}
private:
void operator= (LessThan&); // not assignable
};
std::size_t LessThan::funcalls_;
/**************************************************************************/
template <class T, class ForwardIterator>
void test_binary_search (int line,
const char *src_str,
char val_char,
bool exp_res,
std::size_t ncomp,
const ForwardIterator &it,
const T*,
bool predicate)
{
RW_ASSERT (0 != src_str);
const char* const tname = "UserClass";
const char* const itname = type_name (it, (T*)0);
const char* const funname = predicate ? "LessThan" : "operator<()";
const std::size_t nsrc = std::strlen (src_str);
T* const xsrc = T::from_char (src_str, nsrc);
T* const xsrc_end = xsrc + nsrc;
// construct the source range to pass to the algorithm
const ForwardIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const ForwardIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
// construct the object to pass to the algorithm
// the type of the object is distinct from the iterator's value_type
// to detect unwarranted assumptions made by the implementation
Y value (0, 0 /* dummy arguments */);
value.xval_.data_.val_ = val_char;
// construct the Compare function object to pass to the algorithm
// when `predicate' is true
const LessThan comp (0, 0 /* dummy arguments */);
// reset the counter of invocations of T::operator<()
T::n_total_op_lt_ = 0;
// invoke the appropriate form of the algorithm, storing
// the resturned value
const bool result = predicate
? std::binary_search (first, last, value, comp)
: std::binary_search (first, last, value);
// silence bogus EDG eccp 3.6 remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (result);
rw_assert (result == exp_res, 0, line,
"binary_search <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
"expected %s, got %s",
itname, tname, predicate, funname, src_str, val_char,
exp_res ? "true" : "false", result ? "true" : "false");
// verify complexity
const std::size_t n_ops = predicate
? LessThan::funcalls_ : T::n_total_op_lt_;
rw_assert (n_ops <= ncomp, 0, line,
"binary_search <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
"complexity: invoked %4$s at most %zu times, got %zu",
itname, tname, predicate, funname, src_str, val_char,
ncomp, n_ops);
delete[] xsrc;
}
/**************************************************************************/
template <class T, class ForwardIterator>
void test_binary_search (const ForwardIterator &it,
const T*,
bool predicate)
{
const char* const itname = type_name (it, (T*)0);
const char* const funname = predicate ? "LessThan" : "operator<()";
rw_info (0, 0, 0,
"std::binary_search (%s, %1$s, const UserClass&%{?}, %s%{;})",
itname, predicate, funname);
#define TEST(str, val, res, comp) \
test_binary_search (__LINE__, str, val, res, std::size_t (comp), \
it, (T*)0, predicate)
// +--------------- source sequence
// | +--------- value argument
// | | +----- expected result: true/false
// | | | +-- complexity: at most (log(last - first) + 2)
// | | | | comparisons (or applications of the predicate)
// | | | |
// V V V V
TEST ("", 'a', false, 0);
TEST ("a", 'a', true, 2);
TEST ("a", 'b', false, 2);
TEST ("b", 'a', false, 2);
TEST ("aa", 'a', true, 3);
TEST ("ab", 'a', true, 3);
TEST ("ab", 'b', true, 3);
TEST ("bb", 'a', false, 3);
TEST ("abcdefghij", 'a', true, 6);
TEST ("abcdefghij", 'c', true, 6);
TEST ("abcdefghij", 'f', true, 6);
TEST ("abcdefghij", 'h', true, 6);
TEST ("abcdefghij", 'j', true, 6);
TEST ("aacceeggii", 'c', true, 6);
TEST ("aacceeggii", 'g', true, 6);
TEST ("aacceeggii", 'b', false, 6);
TEST ("aacceeggii", 'f', false, 6);
TEST ("aacceeggii", 'j', false, 6);
TEST ("cccceeggii", 'a', false, 6);
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T>
void test_binary_search (const T*,
bool predicate)
{
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
"bool std::binary_search (%1$s, %1$s, const %2$s&%{?}, %s%{;})",
"ForwardIterator", "UserClass", predicate, "Compare", predicate,
"Compare");
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "ForwardIterator test disabled");
}
else {
test_binary_search (fwd_iter, (T*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
}
else {
test_binary_search (bidir_iter, (T*)0, predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
}
else {
test_binary_search (rand_iter, (T*)0, predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_binary_search ((UserClass*)0, false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"test of the Predicate form of std::binary_search disabled");
}
else {
test_binary_search ((UserClass*)0, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.binary.search",
0 /* no comment */,
run_test,
"|-no-Predicate# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,408 @@
/***************************************************************************
*
* 25.copy.cpp - test exercising 25.2.1 [lib.alg.copy]
*
* $Id: 25.copy.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for copy
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()...
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<assign<base<> > >
copy (InputIter<const_cvt<base<>, assign<base<> > > >,
InputIter<const_cvt<base<>, assign<base<> > > >,
OutputIter<assign<base<> > >);
template
BidirIter<assign<base<> > >
copy_backward (BidirIter<const_cvt<base<>, assign<base<> > > >,
BidirIter<const_cvt<base<>, assign<base<> > > >,
BidirIter<assign <base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// exercises std::copy()
template <class InputIterator, class OutputIterator, class T>
void test_copy (std::size_t N,
const InputIterator &input_iter,
const OutputIterator &output_iter,
const T* )
{
static const char* const it1name = type_name (input_iter, (T*) 0);
static const char* const it2name = type_name (output_iter, (T*) 0);
rw_info (0, 0, 0, "std::copy (%s, %1$s, %s)", it1name, it2name);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
// create separate buffers for src and dst to ensure 25.2.1, p3
T* const src = new T [N];
T* const dst = new T [N];
for (std::size_t i = 0; i != N; ++i) {
T* const src_end = src + i + 1;
T* const dst_end = dst + i + 1;
// exercise 25.2.1 - std::copy()
std::size_t last_n_op_assign = T::n_total_op_assign_;
const InputIterator begin =
make_iter (src, src, src_end, input_iter);
const InputIterator end =
make_iter (src_end, src_end, src_end, input_iter);
const OutputIterator dest =
make_iter (dst, dst, dst_end, output_iter);
const OutputIterator result =
std::copy (begin, end, dest);
T* const resptr = result.cur_;
// verify 25.2.1, p2
bool success = resptr == dst_end;
rw_assert (success, 0, __LINE__,
"%zu. copy(%p, %p, %p) == %p, got %p",
i, src, src_end, dst, dst_end, resptr);
if (!success)
break;
// check that algjrithm works correctly
std::size_t j = 0;
for (; j != i + 1; ++j) {
success = src[j].data_.val_ == dst[j].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, __LINE__,
"%zu. copy(%p, %p, %p) mismatch at "
"offset %zu: expected %d, got %d: (%p, %p, %zu)",
i, src, src_end, dst,
j, src[j].data_.val_, dst[j].data_.val_,
dst, dst_end, j);
if (!success)
break;
// verify 25.2.1, p4
success = T::n_total_op_assign_ - last_n_op_assign == i + 1;
rw_assert (success, 0, __LINE__,
"%zu. copy(%p, %p, %p) complexity: ",
"%zu != %zu", i + 1, src, src_end, dst,
T::n_total_op_assign_ - last_n_op_assign, i + 1);
if (!success)
break;
}
delete[] src;
delete[] dst;
}
/**************************************************************************/
// exercises std::copy_backward()
template <class BidirIterator1, class BidirIterator2, class T>
void test_copy_backward (std::size_t N,
const BidirIterator1 &bidir_iter1,
const BidirIterator2 &bidir_iter2,
const T*)
{
static const char* const it1name = type_name (bidir_iter1, (T*) 0);
static const char* const it2name = type_name (bidir_iter2, (T*) 0);
rw_info (0, 0, 0, "std::copy_backward (%s, %1$s, %s)", it1name, it2name);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
// create separate buffers for src and dst to ensure 25.2.1, p3
T* const src = new T [N];
T* const dst = new T [N];
for (std::size_t i = 0; i != N; ++i) {
// default-construct a new T at the end of each sequence
new (src + i) T ();
new (dst + i) T ();
// exercise 25.2.1 - std::copy_backward()
std::size_t last_n_op_assign = T::n_total_op_assign_;
T* const src_end = src + i + 1;
T* const dst_end = dst + i + 1;
const BidirIterator1 begin =
make_iter (src, src, src_end, bidir_iter1);
const BidirIterator1 end =
make_iter (src_end, src, src_end, bidir_iter1);
const BidirIterator2 dest =
make_iter (dst_end, dst, dst_end, bidir_iter2);
const BidirIterator2 result =
std::copy_backward (begin, end, dest);
const T* const resptr = result.cur_;
// verify 25.2.1, p7
bool success = resptr == dst;
rw_assert (success, 0, __LINE__,
"%zu. copy_backward(%p, %p, %p) == %p, got %p",
i, src, src_end, dst_end, dst, resptr);
if (!success)
break;
// verify 25.2.1, p5
std::size_t j = 0;
for (; j != i + 1; ++j) {
success = src[j].data_.val_ == dst[j].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, __LINE__,
"%zu. copy_backward(%p, %p, %p) mismatch at "
"offset %zu: expected %d, got %d: (%p, %p, %zu)",
i, src, src_end, dst_end,
j, src[j].data_.val_, dst[j].data_.val_,
dst, dst_end, j);
if (!success)
break;
// verify 25.2.1, p8
success = T::n_total_op_assign_ - last_n_op_assign == i + 1;
rw_assert (success, 0, __LINE__,
"%zu. copy_backward(%p, %p, %p) complexity: "
"%zu != %zu", i + 1, src, src_end, dst_end,
T::n_total_op_assign_ - last_n_op_assign, i + 1);
if (!success)
break;
}
delete[] src;
delete[] dst;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 32; // --nloops
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class InputIterator, class T>
void test_copy (const std::size_t N, const InputIterator &dummy, T*)
{
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_copy (N, dummy, OutputIter<UserClass>((UserClass*)0,
(UserClass*)0, (UserClass*)0), (UserClass*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_copy (N, dummy, FwdIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy (N, dummy, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy (N, dummy, RandomAccessIter<UserClass>(), (UserClass*)0);
}
}
/**************************************************************************/
static void
test_copy (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"%2$s std::copy (%1$s, %1$s, %2$s)",
"InputIterator", "OutputIterator");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_copy (N, InputIter<UserClass>((UserClass*)0, (UserClass*)0,
(UserClass*)0), (UserClass*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_copy (N, FwdIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy (N, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy (N, RandomAccessIter<UserClass>(), (UserClass*)0);
}
}
/**************************************************************************/
template <class InputIterator, class T>
void test_copy_backward (const std::size_t N, const InputIterator &dummy, T*)
{
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy_backward (N, dummy, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy_backward (N, dummy, RandomAccessIter<UserClass>(),
(UserClass*)0);
}
}
/**************************************************************************/
static void
test_copy_backward (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s> %2$s "
"std::copy_backward (%1$s, %1$s, %2$s)",
"BidirectionalIterator1", "BidirectionalIterator2");
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy_backward (N, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy_backward (N, RandomAccessIter<UserClass>(), (UserClass*)0);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
// check that the number of loops is non-negative
rw_fatal (-1 < rw_opt_nloops, 0, 0,
"number of loops must be non-negative, got %d",
rw_opt_nloops);
const std::size_t N = std::size_t (rw_opt_nloops);
test_copy (N);
test_copy_backward (N);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.copy",
0 /* no comment */, run_test,
"|-nloops#"
"|-no-InputIterator#"
"|-no-OutputIterator#"
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#",
&rw_opt_nloops,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,276 @@
/***************************************************************************
*
* 25.equal.cpp - test exercising 25.1.8 [lib.alg.equal]
*
* $Id: 25.equal.cpp 510071 2007-02-21 15:58:53Z 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.
*
**************************************************************************/
#include <algorithm> // for equal
#include <functional> // for equal_to
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()...
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
bool
equal (InputIter<eq_comp<base<> > >,
InputIter<eq_comp<base<> > >,
InputIter<eq_comp<base<> > >);
template
bool
equal (InputIter<eq_comp<base<> > >,
InputIter<eq_comp<base<> > >,
InputIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
// exercises std::equal()
template <class InputIterator1, class InputIterator2, class T>
void test_equal (std::size_t N,
const InputIterator1 &it1_dummy,
const InputIterator2 &it2_dummy,
T*,
const char *predicate)
{
static const char* const it1name = type_name (it1_dummy, (T*)0);
static const char* const it2name = type_name (it2_dummy, (T*)0);
rw_info (0, 0, 0, "std::equal (%s, %1$s, %s%{?}, %s%{;})",
it1name, it2name, 0 != predicate, predicate);
// generate sequential values for each default constructed UserClass
// for both lists
UserClass::gen_ = gen_seq_2lists;
// use ::operator new() to prevent default initialization
const std::size_t size = N * sizeof (UserClass);
UserClass *buf1 = _RWSTD_STATIC_CAST (UserClass*, ::operator new (size));
UserClass *buf2 = _RWSTD_STATIC_CAST (UserClass*, ::operator new (size));
const std::size_t mid_inx = N / 2;
for (std::size_t i = 0; i != N; ++i) {
// default-construct a new UserClass at the end of the array
new (buf1 + i) UserClass ();
// build a nearly identical array only missing the N/2-th element
if (i != mid_inx)
new (buf2 + i) UserClass ();
}
new (buf2 + mid_inx) UserClass ();
for (std::size_t i = 0; i != N; ++i) {
// exercise 25.1.8 - std::equal()
std::size_t last_n_op_eq = UserClass::n_total_op_eq_;
UserClass* const buf1_end = buf1 + i + 1;
UserClass* const buf2_end = buf2 + i + 1;
const InputIterator1 first1 =
make_iter (buf1, buf1, buf1_end, it1_dummy);
const InputIterator1 last1 =
make_iter (buf1_end, buf1_end, buf1_end, it1_dummy);
const InputIterator2 first2 =
make_iter (buf2, buf2, buf2_end, it2_dummy);
bool res;
if (predicate) {
res = std::equal (first1, last1, first2,
std::equal_to<UserClass>());
}
else {
res = std::equal (first1, last1, first2);
}
// verify 25.1.8, p1
int success = res && i < mid_inx || !res && mid_inx <= i;
const bool equal_expected = i < mid_inx;
rw_assert (success, 0, __LINE__,
"%zu. equal(%s, %2$s, %s%{?}, %s%{;}) == %d, got %d",
i + 1, it1name, it2name,
0 != predicate, predicate,
equal_expected, res);
// verify 25.1.8, p2
success = UserClass::n_total_op_eq_ - last_n_op_eq <= (N + 1);
rw_assert (success, 0, __LINE__,
"%zu. equal(%s, %2$s, %s%s%{?}, %s%{;}) complexity: "
"%zu <= %zu",
i + 1, it1name, it2name,
0 != predicate, predicate,
UserClass::n_total_op_eq_, i + 1);
if (!success)
break;
}
::operator delete (buf1);
::operator delete (buf2);
}
/**************************************************************************/
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
template <class InputIterator, class T>
void test_equal (const InputIterator &dummy, T*, const char *predicate)
{
static const std::size_t N = 1024;
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_equal (N, dummy, InputIter<UserClass>((UserClass*)0,
(UserClass*)0, (UserClass*)0), (UserClass*)0,
predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_equal (N, dummy, FwdIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_equal (N, dummy, BidirIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_equal (N, dummy, RandomAccessIter<UserClass>(), (UserClass*)0,
predicate);
}
}
/**************************************************************************/
static void
test_equal (const char *predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"bool std::equal (%1$s, %1$s, %2$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2",
0 != predicate, predicate);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_equal (InputIter<UserClass>((UserClass*)0, (UserClass*)0,
(UserClass*)0), (UserClass*)0, predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_equal (FwdIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_equal (BidirIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_equal (RandomAccessIter<UserClass>(), (UserClass*)0, predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_equal (0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
test_equal ("std::equal_to<UserClass>");
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.equal",
0 /* no comment */, run_test,
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate",
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,340 @@
/***************************************************************************
*
* 25.equal.range.cpp - test exercising 25.3.3.3 [lib.equal.range]
*
* $Id: 25.equal.range.cpp 510970 2007-02-23 14:57:45Z 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 2006 Rogue Wave Software.
*
**************************************************************************/
#include <rw/_config.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// disable implicit inclusion to work around a limitation
// of IBM VisualAge 5.0 (see PR #26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#include <algorithm> // for equal_range()
#include <cstring> // for strlen()
#include <alg_test.h> // for iterators
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test(), ...
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
pair <FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > > >
equal_range (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
const lt_comp<assign<base<cpy_ctor> > >&);
template
pair <FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > > >
equal_range (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
const lt_comp<assign<base<cpy_ctor> > >&,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// distinct and not Less-Than-Comparable with class T (except as
// defined below) to detect unwarranted assumptions made by the
// implementation of the algorithms
struct Y
{
UserClass xval_;
// not Default-Constructible
Y (char val, int /*dummy */): xval_ () {
typedef unsigned char UChar;
xval_.data_.val_ = int (UChar (val));
}
// CopyConstructible
Y (const Y &rhs): xval_ (rhs.xval_) { }
private:
void operator=(Y&); // not Assignable
};
inline conv_to_bool
operator< (const UserClass &lhs, const Y &rhs)
{
return conv_to_bool::make (lhs < rhs.xval_);
}
inline conv_to_bool
operator< (const Y &lhs, const UserClass &rhs)
{
return conv_to_bool::make (lhs.xval_ < rhs);
}
// predicate used as the Compare argument to upper_bound()
struct LessThan
{
static std::size_t funcalls_;
LessThan (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &lhs, const Y &rhs) {
++funcalls_;
return conv_to_bool::make (lhs < rhs.xval_);
}
conv_to_bool operator() (const Y &lhs, const UserClass &rhs) {
++funcalls_;
return conv_to_bool::make (lhs.xval_ < rhs);
}
private:
void operator= (LessThan&); // not assignable
};
std::size_t LessThan::funcalls_;
/**************************************************************************/
template <class T, class ForwardIterator>
void test_equal_range (int line,
const char *src_str,
char val_char,
std::size_t result_loff,
std::size_t result_uoff,
std::size_t ncomp,
const ForwardIterator &it,
const T*,
bool predicate)
{
RW_ASSERT (0 != src_str);
const char* const tname = "UserClass";
const char* const itname = type_name (it, (T*)0);
const char* const funname = predicate ? "LessThan" : "operator<()";
const std::size_t nsrc = std::strlen (src_str);
T* const xsrc = T::from_char (src_str, nsrc + 1);
T* const xsrc_end = xsrc + nsrc;
if (nsrc < result_uoff)
result_uoff = nsrc;
// construct the source range to pass to the algorithm
const ForwardIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const ForwardIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
// construct the object to pass to the algorithm
// the type of the object is distinct from the iterator's value_type
// to detect unwarranted assumptions made by the implementation of
// the algorithm
const Y value (val_char, 0 /* dummy */);
// construct the Compare function object to pass to the algorithm
// when `predicate' is true
const LessThan comp (0, 0 /* dummy arguments */);
// reset the counter of invocations of T::operator<()
T::n_total_op_lt_ = 0;
// invoke the appropriate form of the algorithm, storing
// the resturned value
const std::pair <ForwardIterator, ForwardIterator> result = predicate
? std::equal_range (first, last, value, comp)
: std::equal_range (first, last, value);
// silence bogus EDG eccp 3.6 remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (result);
// verify correctness
const std::size_t loff = std::size_t (result.first.cur_ - xsrc);
const std::size_t uoff = std::size_t (result.second.cur_ - xsrc);
rw_assert (loff == result_loff && uoff == result_uoff, 0, line,
"equal_range <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
"== first + { %zu, %zu }, got first + { %zu, %zu }",
itname, tname, predicate, funname, src_str, val_char,
loff, uoff, result_loff, result_uoff);
// verify complexity
const std::size_t n_ops = predicate
? LessThan::funcalls_ : T::n_total_op_lt_;
rw_assert (n_ops <= ncomp, 0, line,
"equal_range <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
"complexity: invoked %4$s at most %zu times, got %zu",
itname, tname, predicate, funname, src_str, val_char,
ncomp, n_ops);
delete[] xsrc;
}
/**************************************************************************/
template <class T, class ForwardIterator>
void test_equal_range (const ForwardIterator &it,
const T*,
bool predicate)
{
const char* const itname = type_name (it, (T*)0);
const char* const funname = predicate ? "LessThan" : "operator<()";
rw_info (0, 0, 0,
"std::equal_range (%s, %1$s, const UserClass&%{?}, %s%{;})",
itname, predicate, funname);
#define TEST(str, val, loff, uoff, comp) \
test_equal_range (__LINE__, str, val, std::size_t (loff), \
std::size_t (uoff), std::size_t (comp), \
it, (T*)0, predicate)
// +------------------ source sequence
// | +------------ value argument
// | | +-------- lower offset of the returned pair
// | | | +----- upper offset of the returned pair
// | | | | +-- complexity: at most (2 * log(last - first) + 1)
// | | | | | comparisons (or applications of the predicate)
// | | | | |
// V V V V V
TEST ("", 'a', 0, 0, 0);
TEST ("a", 'a', 0, 1, 2);
TEST ("a", 'b', 1, 1, 1);
TEST ("b", 'a', 0, 0, 2);
TEST ("aa", 'a', 0, 2, 4);
TEST ("ab", 'a', 0, 1, 4);
TEST ("ab", 'b', 1, 2, 3);
TEST ("bb", 'a', 0, 0, 4);
TEST ("ace", 'a', 0, 1, 5);
TEST ("ace", 'b', 1, 1, 4);
TEST ("ace", 'c', 1, 2, 4);
TEST ("ace", 'd', 2, 2, 4);
TEST ("ace", 'e', 2, 3, 4);
TEST ("ace", 'f', 3, 3, 4);
TEST ("aceg", 'a', 0, 1, 6);
TEST ("aceg", 'b', 1, 1, 5);
TEST ("aceg", 'c', 1, 2, 5);
TEST ("aceg", 'd', 2, 2, 5);
TEST ("aceg", 'e', 2, 3, 5);
TEST ("aceg", 'f', 3, 3, 5);
TEST ("aceg", 'g', 3, 4, 5);
TEST ("aceg", 'h', 4, 4, 5);
}
/**************************************************************************/
static int rw_opt_no_fwd_iter;
static int rw_opt_no_bidir_iter;
static int rw_opt_no_rnd_iter;
static int rw_opt_no_predicate;
template <class T>
void test_equal_range (const T*,
bool predicate)
{
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
"std::pair<%1$s, %1$s> std::equal_range "
"(%1$s, %1$s, const %2$s&%{?}, %s%{;})",
"ForwardIterator", "UserClass", predicate, "Compare",
predicate, "Compare");
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "ForwardIterator test disabled");
}
else {
test_equal_range (fwd_iter, (T*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
}
else {
test_equal_range (bidir_iter, (T*)0, predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
}
else {
test_equal_range (rand_iter, (T*)0, predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_equal_range ((UserClass*)0, false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"test of the Predicate form of std::equal_range disabled");
}
else {
test_equal_range ((UserClass*)0, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.equal.range",
0 /* no comment */,
run_test,
"|-no-Predicate# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,321 @@
/***************************************************************************
*
* 25.fill.cpp - test exercising 25.2.5 [lib.alg.fill]
*
* $Id: 25.fill.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for fill
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
fill (FwdIter<assign<base<> > >, FwdIter<assign<base<> > >,
const assign<base<> >&);
template
void
fill_n (OutputIter<assign<base<> > >, Size<int>,
const assign<base<> >&);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// exercises std::fill()
template <class ForwardIterator, class T>
void test_fill (std::size_t N,
const ForwardIterator &dummy_iter,
const T*)
{
static const char* const itname = type_name (dummy_iter, (T*)0);
static const char* const tname = "UserClass";
rw_info (0, 0, 0, "void std::fill (%s, %1$s, const %s&)", itname, tname);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
T* const buf = new T [N];
for (std::size_t i = 0; i < N; ++i) {
T* const buf_end = buf + i;
const ForwardIterator begin =
make_iter (buf, buf, buf_end, dummy_iter);
const ForwardIterator end =
make_iter (buf_end, buf_end, buf_end, dummy_iter);
const T value;
// the number of invocations of the assignment operator
std::size_t n_op_assign = T::n_total_op_assign_;
std::fill (begin, end, value);
// compute the number of invocations of the assignment operator
// by the algorithm
n_op_assign = T::n_total_op_assign_ - n_op_assign;
bool success = true;
// verify 25.2.5, p2
std::size_t j = 0;
for ( ; success && j != i; ++j) {
success = buf [j].data_.val_ == value.data_.val_;
}
if (!rw_assert (success, 0, __LINE__,
"%zu. fill (%s, %2$s, const %s&): buf [%zu]: %d != %d",
i, itname, tname, j, buf [j].data_.val_,
value.data_.val_))
break;
// verify the complexity requirements:
// Exactly last - first assignments.
if (!rw_assert (n_op_assign == i, 0, __LINE__,
"%zu. fill (%s, %2$s, const %s&) expected "
"%zu invocations of %2$s::operator=(); got %zu",
i, itname, tname, i, n_op_assign))
break;
}
delete[] buf;
}
/**************************************************************************/
// exercises std::fill_n()
template <class OutputIterator, class Size, class T>
void test_fill_n (std::size_t N,
const OutputIterator &dummy_iter,
const Size*,
const T*)
{
static const char* const itname = type_name (dummy_iter, (T*)0);
static const char* const szname = "Size<int>";
static const char* const tname = "UserClass";
rw_info (0, 0, 0, "void std::fill_n (%s, %s, const %s&)",
itname, szname, tname);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
T* const buf = new T [N];
for (std::size_t i = 0; i < N; ++i) {
T* const buf_end = buf + i;
const OutputIterator begin =
make_iter (buf, buf, buf_end, dummy_iter);
const Size n (i, 0 /* dummy */);
const T value;
// the number of invocations of the assignment operator
std::size_t n_op_assign = T::n_total_op_assign_;
std::fill_n (begin, n, value);
// compute the number of invocations of the assignment operator
n_op_assign = T::n_total_op_assign_ - n_op_assign;
bool success = true;
// verify 25.2.5, p2
std::size_t j = 0;
for ( ; success && j != i; ++j) {
success = buf [j].data_.val_ == value.data_.val_;
}
rw_assert (success, 0, __LINE__,
"%zu. fill_n (%s, %s, const %s&): buf [%zu]: %d != %d",
i, itname, szname, tname, j, buf [j].data_.val_,
value.data_.val_);
if (!success)
break;
success = n_op_assign == i;
rw_assert (success, 0, __LINE__,
"%zu. fill_n (%s, %s, const %s&) complexity: "
"%zu != %zu", i, itname, szname, tname,
n_op_assign, i);
if (!success)
break;
}
delete[] buf;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 32; // --nloops
/* extern */ int rw_opt_no_fill; // --no-fill
/* extern */ int rw_opt_no_fill_n; // --no-fill_n
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
static void
test_fill (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"void std::fill (%1$s, %1$s, const %2$s&)",
"ForwardIterator", "T");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_fill (N, FwdIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_fill (N, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_fill (N, RandomAccessIter<UserClass>(), (UserClass*)0);
}
}
/**************************************************************************/
static void
test_fill_n (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s> "
"void std::fill_n (%1$s, %2$s, const %3$s&)",
"OutputIterator", "Size", "T");
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_fill_n (N, OutputIter<UserClass>(0, 0, 0), (Size<int>*)0,
(UserClass*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_fill_n (N, FwdIter<UserClass>(), (Size<int>*)0, (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_fill_n (N, BidirIter<UserClass>(), (Size<int>*)0, (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_fill_n (N, RandomAccessIter<UserClass>(), (Size<int>*)0,
(UserClass*)0);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
// check that the number of loops is non-negative
rw_fatal (-1 < rw_opt_nloops, 0, 0,
"number of loops must be non-negative, got %d",
rw_opt_nloops);
const std::size_t N = std::size_t (rw_opt_nloops);
if (rw_opt_no_fill) {
rw_note (0, __FILE__, __LINE__, "std::fill test disabled");
}
else {
test_fill (N);
}
if (rw_opt_no_fill_n) {
rw_note (0, __FILE__, __LINE__, "std::fill_n test disabled");
}
else {
test_fill_n (N);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.fill",
0 /* no comment */, run_test,
"|-nloops# "
"|-no-fill# "
"|-no-fill_n# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_nloops,
&rw_opt_no_fill,
&rw_opt_no_fill_n,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,289 @@
/***************************************************************************
*
* find.cpp - test exercising 25.1.2 [lib.alg.find]
*
* $Id: 25.find.cpp 510970 2007-02-23 14:57:45Z 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 2000-2006 Rogue Wave Software.
*
**************************************************************************/
#include <algorithm> // for find()
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
InputIter<eq_comp<base<> > >
find (InputIter<eq_comp<base<> > >, InputIter<eq_comp<base<> > >,
const eq_comp<base<> >&);
template
InputIter<eq_comp<base<> > >
find_if (InputIter<eq_comp<base<> > >, InputIter<eq_comp<base<> > >,
predicate<eq_comp<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Predicate
{
static std::size_t funcalls_;
Predicate (const T &val, int /* dummy */)
: val_ (val) {
funcalls_ = 0;
}
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
ConvertibleToBool operator() (T obj) /* not const */ {
++funcalls_;
return ConvertibleToBool (obj == val_);
}
private:
void operator= (Predicate&);
const T &val_;
};
template <class T>
std::size_t Predicate<T>::funcalls_;
/**************************************************************************/
template <class InputIterator>
void test_find (int line, // line number of test case
const char *src, // source sequence
std::size_t findoff, // offset of the element to find
InputIterator dummy_iter,
bool test_pred)
{
static const char* const itname = type_name (dummy_iter, (UserClass*)0);
static const char* const pname = test_pred ? "Predicate" : "operator==";
const std::size_t nsrc = std::strlen (src);
// normalize offset
if (nsrc < findoff)
findoff = nsrc;
// create always at least 1 element (used to test failed searches)
UserClass* const tsrc = UserClass::from_char (src, nsrc + 1);
UserClass* const src_begin = tsrc;
UserClass* const src_end = tsrc + nsrc;
// current [first, last)
const InputIterator first (src_begin, src_begin, src_end);
const InputIterator last (src_end, src_begin, src_end);
// get a reference to the object to find (when findoff == nsrc
// the sought for element is outside the source range and won't
// be found)
const UserClass &to_find = tsrc [findoff];
// construct a predicate object to use with find_if
const Predicate<UserClass> pred (to_find, 0 /* dummy */);
// reset the operator==() counter
UserClass::n_total_op_eq_ = 0;
// invoke find() or find_if(), depending on the predicate flag
const InputIterator res = test_pred ?
std::find_if (first, last, pred) : std::find (first, last, to_find);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (res);
// verify 25.1.5 p2
if (!rw_assert (res.cur_ == first.cur_ + findoff, 0, line,
"line %d: find%{?}_if%{;} (%s = \"%s\", ..., '%c')"
" == (it + %zu), got (it + %td)",
__LINE__, test_pred, itname, src, to_find.data_.val_,
findoff, res.cur_ - first.cur_)) {
delete[] tsrc;
return;
}
// verify 25.1.5 p3
// Complexity: At most last - first applications
// of the corresponding predicate.
// The complexity when find is successful is actually
// (res - first) applications of the corresponding predicate.
const std::size_t npreds =
test_pred ? pred.funcalls_ : UserClass::n_total_op_eq_;
rw_assert (npreds <= findoff + 1, 0, line,
"line %d: find%{?}_if%{;} (%s = \"%s\", ..., '%c') "
"invoked %s %zu times, expected no more than %zu",
__LINE__, test_pred, itname, src, to_find.data_.val_,
pname, npreds, findoff + 1);
delete[] tsrc;
}
/**************************************************************************/
template <class InputIterator>
void test_find (InputIterator dummy_iter, bool test_pred)
{
static const char* const itname = type_name (dummy_iter, (UserClass*)0);
rw_info (0, 0, 0, "std::find%{?}_if%{;} (%s, %2$s, "
"%{?}Predicate%{:}const UserClass&%{;})",
test_pred, itname, test_pred);
#define TEST(src, off_find) \
test_find (__LINE__, src, std::size_t (off_find), \
dummy_iter, test_pred)
// +------------------ subject sequence
// | +--- offset of the value to find (-1 for none)
// | | also the offset of the returned iterator
// | |
// | |
// v v
TEST ("", -1);
TEST ("a", 0);
TEST ("aa", 0);
TEST ("ab", 1);
TEST ("aaa", 0);
TEST ("abb", 1);
TEST ("abc", 2);
TEST ("abcc", 2);
TEST ("abcd", 3);
TEST ("abcde", 4);
TEST ("abcdef", 5);
TEST ("abcdefg", 6);
TEST ("abcdefgh", 7);
TEST ("abcdefghi", 8);
TEST ("abcdefghij", 9);
TEST ("abcdefghijk", 10);
TEST ("abcdefghijk", -1);
}
/**************************************************************************/
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
static void
test_find (bool test_pred)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"%1$s std::find%{?}_if%{;} (%1$s, %1$s, "
"%{?}%2$s%{:}const %2$s&%{;})",
"InputIterator", test_pred ? "Predicate" : "T",
test_pred);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_find (InputIter<UserClass>(0, 0, 0), test_pred);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_find (ConstFwdIter<UserClass>(), test_pred);
test_find (FwdIter<UserClass>(), test_pred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_find (ConstBidirIter<UserClass>(), test_pred);
test_find (BidirIter<UserClass>(), test_pred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_find (ConstRandomAccessIter<UserClass>(), test_pred);
test_find (RandomAccessIter<UserClass>(), test_pred);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_find (false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
test_find (true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.find",
0 /* no comment */, run_test,
"|-no-InputIterator#"
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate#",
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,344 @@
/***************************************************************************
*
* find_end.cpp - test exercising 25.1.3 [lib.alg.find.end]
*
* $Id: 25.find.end.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for find_end()
#include <functional> // for equal_to
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
FwdIter<eq_comp<base<> > >
find_end (FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >);
template
FwdIter<eq_comp<base<> > >
find_end (FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// used to initialize an array of objects of type T
static const char *tinit_begin;
int tinit ()
{
typedef unsigned char UChar;
return UChar (*tinit_begin++);
}
// exercises std::find_end()
template <class ForwardIterator1, class ForwardIterator2, class T>
void do_test (int line, // line number of test case
const char *src, // source sequence
const char *fseq, // sequence to be found
std::size_t resoff, // offset of result
ForwardIterator1 &dummy_iter1,
ForwardIterator2 &dummy_iter2,
const T*,
const char *predicate)
{
static const char* const it1name = type_name (dummy_iter1, (T*)0);
static const char* const it2name = type_name (dummy_iter2, (T*)0);
const std::size_t nsrc = std::strlen (src);
const std::size_t nfseq = std::strlen (fseq);
if (std::size_t (-1) == resoff)
resoff = nsrc;
// have the T default ctor initialize objects from `src'
tinit_begin = src;
T::gen_ = tinit;
T* const tsrc = new T [nsrc];
T* const src_begin = tsrc;
T* const src_end = tsrc + nsrc;
// have the T default ctor initialize sequence to be found
tinit_begin = fseq;
T* const tfseq = new T [nfseq];
T* const fseq_begin = tfseq;
T* const fseq_end = tfseq + nfseq;
// create iterators
const ForwardIterator1 first1 =
make_iter (src_begin, src_begin, src_end, dummy_iter1);
const ForwardIterator1 last1 =
make_iter (src_end, src_begin, src_end, dummy_iter1);
const ForwardIterator2 first2 =
make_iter (fseq_begin, fseq_begin, fseq_end, dummy_iter2);
const ForwardIterator2 last2 =
make_iter (fseq_end, fseq_begin, fseq_end, dummy_iter2);
// compute the number of invocations of the predicate
std::size_t last_n_op_assign = T::n_total_op_assign_;
const ForwardIterator1 res = predicate ?
std::find_end (first1, last1, first2, last2, std::equal_to<T>())
: std::find_end (first1, last1, first2, last2);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (res);
bool success = res.cur_ == first1.cur_ + resoff;
rw_assert (success, 0, line,
"line %d: find_end<%s, %s>(it = \"%s\", \"%s\")"
" == (it + %zu), got (it + %td)",
__LINE__, it1name, it2name, src, fseq,
resoff, res.cur_ - first1.cur_);
if (!success) {
delete[] tsrc;
delete[] tfseq;
return;
}
if (res.cur_ != last1.cur_) {
std::size_t j = 0;
for ( ; j < nfseq; ++j) {
success = (res.cur_ + j)->data_.val_ == fseq[j];
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: find_end<%s, %s>(it = \"%s\", \"%s\")"
" expected value %c got %c at %zu position",
__LINE__, it1name, it2name, src, fseq,
fseq[j], (res.cur_ + j)->data_.val_, j);
if (!success) {
delete[] tsrc;
delete[] tfseq;
return;
}
}
success =
T::n_total_op_assign_ - last_n_op_assign <= nfseq * (nsrc - nfseq + 1);
rw_assert (success, 0, line,
"line %d: find_end<%s, %s>(it = \"%s\", \"%s\")"
" %s invoked %zu times, expected no more than %td",
__LINE__, it1name, it2name, src, fseq,
predicate ? predicate : "comparison operator",
T::n_total_op_eq_, nfseq * (nsrc - nfseq + 1));
delete[] tsrc;
delete[] tfseq;
}
/**************************************************************************/
template <class ForwardIterator1, class ForwardIterator2, class T>
void run_tests (const ForwardIterator1& dummy_iter1,
const ForwardIterator2& dummy_iter2,
const T*, const char* predicate)
{
static const char* const it1name = type_name (dummy_iter1, (T*)0);
static const char* const it2name = type_name (dummy_iter2, (T*)0);
rw_info (0, 0, 0, "%s std::find_end (%1$s, %1$s, %s, %2$s%{?}, %s%{;})",
it1name, it2name, 0 != predicate, predicate);
#define TEST(src, fnd, off_res) \
do_test (__LINE__, src, fnd, std::size_t (off_res), \
dummy_iter1, dummy_iter2, (UserClass*)0, predicate)
// +------------------ subject sequence
// | +--- sequence to be found
// | |
// | | +-- offset of returned iterator,
// | | | -1 denotes the end of sequence
// v v v
TEST ("abcdefghijk", "ab", 0);
TEST ("abcdefghijk", "bc", 1);
TEST ("abcdefghijk", "cd", 2);
TEST ("abcdefghijk", "de", 3);
TEST ("abcdefghijk", "ef", 4);
TEST ("abcdefghijk", "fg", 5);
TEST ("abcdefghijk", "gh", 6);
TEST ("abcdefghijk", "hi", 7);
TEST ("abcdefghijk", "ij", 8);
TEST ("abcdefghijk", "jk", 9);
TEST ("ababcdefghij", "ab", 2);
TEST ("abcbcdefghij", "bc", 3);
TEST ("abcdcdefghij", "cd", 4);
TEST ("abcdedefghij", "de", 5);
TEST ("abcdefefghij", "ef", 6);
TEST ("abcdefgfghij", "fg", 7);
TEST ("abcdefghghij", "gh", 8);
TEST ("abcdefghihij", "hi", 9);
TEST ("bcdefghijijk", "ij", 9);
TEST ("bcdefghijkjk", "jk", 10);
TEST ("", "a", -1);
TEST ("a", "ab", -1);
TEST ("ab", "abc", -1);
TEST ("abc", "abcd", -1);
TEST ("abcd", "abcde", -1);
TEST ("abcde", "abcdef", -1);
TEST ("abcdef", "abcdefg", -1);
TEST ("abcdefg", "abcdefgh", -1);
TEST ("abcdefghijk", "ba", -1);
TEST ("abcdefghijk", "cb", -1);
TEST ("abcdefghijk", "dc", -1);
TEST ("abcdefghijk", "ed", -1);
TEST ("abcdefghijk", "fe", -1);
TEST ("abcdefghijk", "gf", -1);
TEST ("abcdefghijk", "hg", -1);
TEST ("abcdefghijk", "ih", -1);
TEST ("abcdefghijk", "ji", -1);
}
/**************************************************************************/
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
template <class ForwardIterator, class T>
void run_test_find_end (const ForwardIterator& dummy, T*,
const char* predicate)
{
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
run_tests (dummy, FwdIter<T>(), (T*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
run_tests (dummy, BidirIter<T>(), (T*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
run_tests (dummy, RandomAccessIter<T>(), (T*)0, predicate);
}
}
/**************************************************************************/
static void
test_find_end (const char* predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"%1$s std::find_end (%1$s, %1$s, %2$s, %2$s%{?}, %s%{;})",
"ForwardIterator1", "ForwardIterator2",
0 != predicate, predicate);
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
run_test_find_end (FwdIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
run_test_find_end (BidirIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
run_test_find_end (RandomAccessIter<UserClass>(), (UserClass*)0,
predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_find_end (0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
test_find_end ("std::equal_to<UserClass>");
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.find.end",
0 /* no comment */, run_test,
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate#",
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,367 @@
/***************************************************************************
*
* find.first.cpp - test exercising 25.1.4 [lib.alg.find.first.of]
*
* $Id: 25.find.first.cpp 510071 2007-02-21 15:58:53Z 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.
*
**************************************************************************/
#include <algorithm> // for find_first_of
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
FwdIter<eq_comp<base<> > >
find_first_of (FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >);
template
FwdIter<eq_comp<base<> > >
find_first_of (FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >, FwdIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T, class U>
struct EqualityPredicate
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class
// from being default constructible
EqualityPredicate (T* /* dummy */, U* /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
ConvertibleToBool operator() (const T &x, const U &y) /* non-const */ {
++funcalls_;
return x == y;
}
};
template <class T, class U>
std::size_t EqualityPredicate<T, U>::funcalls_;
/**************************************************************************/
// used to initialize an array of objects of type T
static const char *tinit_begin;
int tinit ()
{
typedef unsigned char UChar;
return UChar (*tinit_begin++);
}
// exercises std::find_end()
template <class ForwardIterator1, class ForwardIterator2,
class Predicate, class T>
void do_test (int line, // line number of test case
const char *src, // source sequence
const char *fseq, // sequence to be found
std::size_t resoff, // offset of result
ForwardIterator1 &dummy_iter1,
ForwardIterator2 &dummy_iter2,
const T*,
const Predicate *pred)
{
static const char* const it1name = type_name (dummy_iter1, (T*)0);
static const char* const it2name = type_name (dummy_iter2, (T*)0);
static const char* const pname = pred ? "Predicate" : "operator==";
const std::size_t nsrc = std::strlen (src);
const std::size_t nfseq = std::strlen (fseq);
if (std::size_t (-1) == resoff)
resoff = nsrc;
// have the T default ctor initialize objects from `src'
tinit_begin = src;
T::gen_ = tinit;
T* const tsrc = new T [nsrc];
T* const src_begin = tsrc;
T* const src_end = tsrc + nsrc;
// have the T default ctor initialize sequence to be found
tinit_begin = fseq;
T* const tfseq = new T [nfseq];
T* const fseq_begin = tfseq;
T* const fseq_end = tfseq + nfseq;
// create iterators
const ForwardIterator1 first1 =
make_iter (src_begin, src_begin, src_end, dummy_iter1);
const ForwardIterator1 last1 =
make_iter (src_end, src_begin, src_end, dummy_iter1);
const ForwardIterator2 first2 =
make_iter (fseq_begin, fseq_begin, fseq_end, dummy_iter2);
const ForwardIterator2 last2 =
make_iter (fseq_end, fseq_begin, fseq_end, dummy_iter2);
// compute the number of invocations of the operator==()
std::size_t last_n_op_assign = T::n_total_op_assign_;
const Predicate fun((T*)0, (T*)0); // dummy arguments
const ForwardIterator1 res = pred ?
std::find_first_of (first1, last1, first2, last2, fun)
: std::find_first_of (first1, last1, first2, last2);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (res);
if (!rw_assert (res.cur_ == first1.cur_ + resoff, 0, line,
"line %d: find_first_of<%s, %s>(it = \"%s\", \"%s\")"
" == (it + %zu), got (it + %td)",
__LINE__, it1name, it2name, src, fseq,
resoff, res.cur_ - first1.cur_)) {
delete[] tsrc;
delete[] tfseq;
return;
}
const std::size_t npreds = pred ?
fun.funcalls_ : T::n_total_op_assign_ - last_n_op_assign;
rw_assert (npreds <= nfseq * nsrc, 0, line,
"line %d: find_first_of<%s, %s>(it = \"%s\", \"%s\")"
"%s invoked %zu times, expected no more than %td",
__LINE__, it1name, it2name, src, fseq, pname,
npreds, nfseq * nsrc);
delete[] tsrc;
delete[] tfseq;
}
/**************************************************************************/
template <class ForwardIterator1, class ForwardIterator2,
class Predicate, class T>
void run_tests (const ForwardIterator1 &dummy_iter1,
const ForwardIterator2 &dummy_iter2,
const T*,
const Predicate *pred)
{
static const char* const it1name = type_name (dummy_iter1, (T*)0);
static const char* const it2name = type_name (dummy_iter2, (T*)0);
rw_info (0, 0, 0,
"%s std::find_first_of (%1$s, %1$s, %s, %2$s%{?}, %s%{;})",
it1name, it2name, 0 != pred, "Predicate");
#define TEST(src, fnd, off_res) \
do_test (__LINE__, src, fnd, std::size_t (off_res), \
dummy_iter1, dummy_iter2, (UserClass*)0, pred)
// +------------------ subject sequence
// | +--- sequence to be found
// | |
// | | +-- offset of returned iterator,
// | | | -1 denotes the end of sequence
// v v v
TEST ("abcdefghijk", "a", 0);
TEST ("abcdefghijk", "b", 1);
TEST ("abcdefghijk", "c", 2);
TEST ("abcdefghijk", "d", 3);
TEST ("abcdefghijk", "e", 4);
TEST ("abcdefghijk", "f", 5);
TEST ("abcdefghijk", "g", 6);
TEST ("abcdefghijk", "h", 7);
TEST ("abcdefghijk", "i", 8);
TEST ("abcdefghijk", "j", 9);
TEST ("abcdefghijk", "k", 10);
TEST ("aabcdefghijk", "a", 0);
TEST ("abbcdefghijk", "b", 1);
TEST ("abccdefghijk", "c", 2);
TEST ("abcddefghijk", "d", 3);
TEST ("abcdeefghijk", "e", 4);
TEST ("abcdeffghijk", "f", 5);
TEST ("abcdefgghijk", "g", 6);
TEST ("abcdefghhijk", "h", 7);
TEST ("abcdefghijjk", "i", 8);
TEST ("abcdefghijjk", "j", 9);
TEST ("abcdefghijkk", "k", 10);
TEST ("bbcdefghijk", "ab", 0);
TEST ("accdefghijk", "bc", 1);
TEST ("abddefghijk", "cd", 2);
TEST ("abceefghijk", "de", 3);
TEST ("abcdffghijk", "ef", 4);
TEST ("abcdegghijk", "fg", 5);
TEST ("abcdefhhijk", "gh", 6);
TEST ("abcdefgiijk", "hi", 7);
TEST ("abcdefghjjk", "ij", 8);
TEST ("abcdefghikk", "jk", 9);
TEST ("bbcdefghijk", "a", -1);
TEST ("accdefghijk", "b", -1);
TEST ("abddefghijk", "c", -1);
TEST ("abceefghijk", "d", -1);
TEST ("abcdffghijk", "e", -1);
TEST ("abcdegghijk", "f", -1);
TEST ("abcdefhhijk", "g", -1);
TEST ("abcdefgiijk", "h", -1);
TEST ("abcdefghjjk", "i", -1);
TEST ("abcdefghikk", "j", -1);
TEST ("", "a", -1);
TEST ("abcdefghijk", "", -1);
}
/**************************************************************************/
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
template <class ForwardIterator, class Predicate, class T>
void run_test (const ForwardIterator &dummy, T*, Predicate* pred)
{
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
run_tests (dummy, FwdIter<T>(), (T*)0, pred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
run_tests (dummy, BidirIter<T>(), (T*)0, pred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
run_tests (dummy, RandomAccessIter<T>(), (T*)0, pred);
}
}
/**************************************************************************/
static void
run_test (bool test_predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"%1$s std::find_first_of (%1$s, %1$s, %2$s, %2$s%{?}, %s%{;})",
"ForwardIterator1", "ForwardIterator2",
0 != test_predicate, "Predicate");
typedef EqualityPredicate<UserClass, UserClass> EqPred;
const EqPred* const pred = test_predicate ? (EqPred*)1 : (EqPred*)0;
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
run_test (FwdIter<UserClass>(), (UserClass*)0, pred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
run_test (BidirIter<UserClass>(), (UserClass*)0, pred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
run_test (RandomAccessIter<UserClass>(), (UserClass*)0, pred);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
run_test (false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
run_test (true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.find.first.of",
0 /* no comment */, run_test,
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate#",
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,253 @@
/***************************************************************************
*
* 25.for_each.cpp - test exercising 25.1.1 [lib.alg.foreach]
*
* $Id: 25.for.each.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for for_each
#include <cstddef> // for ptrdiff_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test(), ...
/**************************************************************************/
struct FunctionBase
{
static std::size_t funcalls_;
static int sum_;
bool is_const_;
FunctionBase (bool is_const)
: is_const_ (is_const) {
funcalls_ = 0;
sum_ = 0;
}
private:
void operator= (FunctionBase&); // not assignable
};
std::size_t FunctionBase::funcalls_;
int FunctionBase::sum_;
struct ConstFunction: FunctionBase
{
// dummy arguments provided to prevent the class
// from being default constructible
ConstFunction (int, int): FunctionBase (true) { }
void operator() (UserClass val) /* not const */ {
++funcalls_;
sum_ += val.data_.val_;
}
static const char* name () { return "ConstFunction"; }
};
struct MutableFunction: FunctionBase
{
// dummy arguments provided to prevent the class
// from being default constructible
MutableFunction (int, int): FunctionBase (false) { }
void operator() (UserClass &val) /* not const */ {
++funcalls_;
val.data_.val_ = -val.data_.val_;
}
static const char* name () { return "MutableFunction"; }
};
// exercises std::for_each()
template <class InputIterator, class T, class Function>
void test_for_each (std::size_t N, InputIterator dummy, T*, Function*)
{
static const char* const itname = type_name (dummy, (T*)0);
static const char* const fnname = Function::name ();
rw_info (0, 0, 0, "std::for_each (%s, %1$s, %s)", itname, fnname);
// generate sequential values for each default constructed UserClass
UserClass::gen_ = gen_seq;
UserClass *buf = new UserClass [N];
const int first_val = buf [0].data_.val_;
for (std::size_t i = 0; i != N; ++i) {
UserClass* const buf_end = buf + i;
const InputIterator first (buf, buf, buf_end);
const InputIterator last (buf_end, buf_end, buf_end);
// create a const function object and zero out all its counters
const Function fun (0, 0);
std::for_each (first, last, fun);
// compute the sum of elements in the sequence and check each
// element's value against the expected one
int sum = 0;
for (std::size_t j = 0; j != i; ++j) {
int expect;
if (fun.is_const_) {
// const function object doesn't modify the subject
// sequence; the expected value of the element is
// the same as the original value
expect = first_val + int (j);
}
else {
// non-const function object negates each argument
expect = -(first_val + int (j));
}
// compute the sum (computed by the const function object)
sum += buf [j].data_.val_;
// assert the element value as the same as the expected value
rw_assert (expect == buf [j].data_.val_, 0, __LINE__,
"for_each (%s, %1$s, %s); element [%zu] == %d, got %d",
itname, fnname, j, expect, buf [j].data_.val_);
if (expect != buf [j].data_.val_) {
// break out of both loops on failure
i = N;
break;
}
// restore the original value of the element
buf [j].data_.val_ = first_val + int (j);
}
// assert that for_each invoked the function object's operator()
// exactly as many times as necessary and required
rw_assert (i == fun.funcalls_, 0, __LINE__,
"for_each (%s, %1$s, %s); expected %zu invocations of "
"Function::operator(), got %zu", itname, fnname,
i, fun.funcalls_);
if (fun.is_const_) {
rw_assert (sum == fun.sum_, 0, __LINE__,
"for_each (%s, %1$s, %s); sum of %zu elements == %d, "
"got %d", itname, fnname, sum, fun.sum_);
}
}
delete[] (buf);
}
/**************************************************************************/
static int rw_opt_nloops = 32; // --nloops=#
static int rw_opt_no_input_iter; // --no-InputIterator
static int rw_opt_no_fwd_iter; // --no-ForwardIterator
static int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
static int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
static int
run_test (int, char*[])
{
const std::size_t N = std::size_t (rw_opt_nloops);
rw_info (0, 0, 0,
"template <class %s, class %s> "
"%2$s std::for_each (%1$s, %1$s, %2$s)",
"InputIterator", "Function");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_for_each (N, InputIter<UserClass>(0, 0, 0), (UserClass*)0,
(ConstFunction*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_for_each (N, ConstFwdIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, FwdIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, FwdIter<UserClass>(), (UserClass*)0,
(MutableFunction*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_for_each (N, ConstBidirIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, BidirIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, BidirIter<UserClass>(), (UserClass*)0,
(MutableFunction*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_for_each (N, ConstRandomAccessIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, RandomAccessIter<UserClass>(), (UserClass*)0,
(ConstFunction*)0);
test_for_each (N, RandomAccessIter<UserClass>(), (UserClass*)0,
(MutableFunction*)0);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.foreach",
0 /* no comment */, run_test,
"|-nloops#0 " // must be non-negative
"|-no-InputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_nloops,
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,356 @@
/***************************************************************************
*
* 25.generate.cpp - test exercising 25.2.6 [lib.alg.generate]
*
* $Id: 25.generate.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for generate
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
template <class T>
struct Generator
{
// return a const reference to avoid requiring
// that T be copy-constructible
const T& operator() () const {
static const union {
void* align_;
unsigned char buf_ [sizeof (T)];
} u = { 0 };
return *(const T*)(const void*)&u;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Generator<UserClass>
{
// dummy arguments provided to prevent Generator
// from being DefaultConstructible
Generator (int, int /* dummy */) {
// use the generator of sequential values
UserClass::gen_ = gen_seq;
}
UserClass operator() () /* non-const */ {
// return a default-constructed UserClass intialized
// to the next sequential value
return UserClass ();
}
};
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void generate (FwdIter<assign<base<> > >, FwdIter<assign<base<> > >,
Generator<assign<base<> > >);
template
void generate_n (OutputIter<assign<base<> > >, std::size_t,
Generator<assign<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// exercises std::generate()
template <class ForwardIterator, class T>
void test_generate (std::size_t N,
const ForwardIterator& gen_iter,
const T* )
{
static const char* const itname = type_name (gen_iter, (T*) 0);
static const char* const genname = "Generator";
rw_info (0, 0, 0,
"void std::generate (%s, %1$s, %s)", itname, genname);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
T *buf = new UserClass [N];
for (std::size_t i = 0; i < N; ++i) {
// exercise 25.2.6, std::generate<> ()
std::size_t last_n_op_assign = T::n_total_op_assign_;
T* const buf_end = buf + i + 1;
const ForwardIterator begin =
make_iter (buf, buf, buf_end, gen_iter);
const ForwardIterator end =
make_iter (buf_end, buf_end, buf_end, gen_iter);
const Generator<T> gen (0, 0);
// store the value of the next element
const int last_val = Generator<T>(0, 0)().data_.val_;
std::generate (begin, end, gen);
bool success = true;
// verify 25.2.6, p2
std::size_t j = 0;
for ( ; j != i; ++j) {
success = (begin.cur_ + j)->data_.val_ == int (last_val + j + 1);
if (!success)
break;
}
rw_assert (success, 0, __LINE__,
"%zu. generate (): buf[%zu]: %d != %d",
i + 1, j, last_val + j + 1, (begin.cur_ + j)->data_.val_ );
if (!success)
break;
// verify 25.2.6, p3
success = T::n_total_op_assign_ - last_n_op_assign == i + 1;
rw_assert (success, 0, __LINE__,
"%zu. generate (): complexity: %zu != %zu",
i + 1, T::n_total_op_assign_ - last_n_op_assign, i + 1);
if (!success)
break;
}
delete[] (buf);
}
/**************************************************************************/
// exercises std::generate_n()
template <class ForwardIterator, class Size, class T>
void test_generate_n (std::size_t N,
const ForwardIterator &gen_iter,
const Size*,
const T*)
{
static const char* const itname = type_name (gen_iter, (T*) 0);
static const char* const szname = "Size<int>";
static const char* const genname = "Generator";
rw_info (0, 0, 0,
"void std::generate_n (%s, %s, %s)", itname, szname, genname);
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
T *buf = new UserClass [N];
for (std::size_t i = 0; i <= N; ++i) {
std::size_t last_n_op_assign = T::n_total_op_assign_;
T* const buf_end = buf + i + 1;
const ForwardIterator begin =
make_iter (buf, buf, buf_end, gen_iter);
const Size n (i, 0);
const Generator<T> gen (0, 0);
// store the value of the next element
const int last_val = Generator<T>(0, 0)().data_.val_;
std::generate_n (begin, n, gen);
bool success = true;
// verify 25.2.6, p2
std::size_t j = 0;
for ( ; j != i; ++j) {
success = (begin.cur_ + j)->data_.val_ == int (last_val + j + 1);
if (!success)
break;
}
rw_assert (success, 0, __LINE__,
"%zu. generate_n (): buf[%zu]: %d != %d",
i + 1, j, last_val + j + 1, (begin.cur_ + j)->data_.val_ );
if (!success)
break;
// verify 25.2.6, p3
success = T::n_total_op_assign_ - last_n_op_assign == i;
rw_assert (success, 0, __LINE__,
"%zu. generate_n (): complexity: %zu != %zu",
i + 1, T::n_total_op_assign_ - last_n_op_assign, i);
if (!success)
break;
}
delete[] (buf);
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 32; // --nloops
/* extern */ int rw_opt_no_generate; // --no-generate
/* extern */ int rw_opt_no_generate_n; // --no-generate_n
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
static void
test_generate (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"void std::generate (%1$s, %1$s, %2$s&)",
"ForwardIterator", "Generator");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_generate (N, FwdIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_generate (N, BidirIter<UserClass>(), (UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_generate (N, RandomAccessIter<UserClass>(), (UserClass*)0);
}
}
/**************************************************************************/
static void
test_generate_n (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s> "
"void std::generate_n (%1$s, %2$s, const %3$s&)",
"OutputIterator", "Size", "Generator");
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_generate_n (N, OutputIter<UserClass>(0, 0, 0), (Size<int>*)0,
(UserClass*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_generate_n (N, FwdIter<UserClass>(), (Size<int>*)0, (UserClass*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_generate_n (N, BidirIter<UserClass>(), (Size<int>*)0,
(UserClass*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_generate_n (N, RandomAccessIter<UserClass>(), (Size<int>*)0,
(UserClass*)0);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
RW_ASSERT (0 <= rw_opt_nloops);
const std::size_t N = std::size_t (rw_opt_nloops);
if (rw_opt_no_generate) {
rw_note (0, __FILE__, __LINE__, "std::generate test disabled");
}
else {
test_generate (N);
}
if (rw_opt_no_generate_n) {
rw_note (0, __FILE__, __LINE__, "std::generate_n test disabled");
}
else {
test_generate_n (N);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.generate",
0 /* no comment */, run_test,
"|-nloops#0 " // argument must be non-negative
"|-no-generate# "
"|-no-generate_n# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_nloops,
&rw_opt_no_generate,
&rw_opt_no_generate_n,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,479 @@
/***************************************************************************
*
* 25.heap.cpp - test exercising 25.3.6 [lib.alg.heap.operations]
*
* $Id: 25.heap.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
// MSVC 6.0 gets an ICE in std::__adjust_heap() in <algorithm.cc>
#if defined (_MSC_VER) && _MSC_VER <= 1300
# define _RWSTD_NO_EXPLICIT_INSTANTIATION
#endif
#include <algorithm> // for make_heap, sort_heap, push_heap, pop_heap
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
// 25.3.6.1 - push_heap [lib.push.heap]
template
void
push_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
push_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
// 25.3.6.2 - pop_heap [lib.pop.heap]
template
void
pop_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
pop_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
// 25.3.6.3 - make_heap [lib.make.heap]
template
void
make_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
make_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
// 25.3.6.4 - sort_heap [lib.sort.heap]
template
void
sort_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
sort_heap (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
// helper function to verify that the sequence is a valid heap
template <class T>
bool is_heap (const T* seq, const std::size_t len)
{
std::size_t parent = 0;
for (std::size_t child = 1; child < len; ++child) {
if (seq [parent].data_.val_ < seq [child].data_.val_)
return false;
if ((child & 1) == 0)
++parent;
}
return true;
}
/**************************************************************************/
// exercises push_heap, pop_heap, make_heap, sort_heap: 25.3.6.1 - 25.3.6.4
template <class T, class Predicate>
void test_heap_operation (int line,
const char *src,
const T*,
const Predicate *ppred,
const std::size_t finx)
{
static const char* const fnames[] = {
"make_heap", "push_heap", "pop_heap", "sort_heap"
};
typedef RandomAccessIter<T> RandIter;
RandIter rand_iter (0, 0, 0);
const char* const itname = type_name (rand_iter, (T*)0);
const char* const fname = fnames[finx];
const char* const funname = Predicate::name();
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xsrc_end = xsrc + nsrc;
int val = xsrc[0].data_.val_;
const RandIter first = make_iter (xsrc, xsrc, xsrc_end, rand_iter);
const RandIter last = make_iter (xsrc_end, xsrc, xsrc_end, rand_iter);
const Predicate pred (0, 0);
const std::size_t last_n_op_lt = T::n_total_op_lt_;
// for convenience
#define HEAP_OP(opname) \
if (ppred) opname (first, last, pred); else opname (first, last)
std::size_t ops = 0;
// exercise heap operation and compute the expected complexity
switch (finx) {
case 0: HEAP_OP (std::make_heap); ops = 3 * nsrc; break;
case 1: HEAP_OP (std::push_heap); ops = ilog2 (nsrc); break;
case 2: HEAP_OP (std::pop_heap); ops = 2 * ilog2 (nsrc); break;
case 3: HEAP_OP (std::sort_heap); ops = nsrc * ilog2 (nsrc); break;
}
const std::size_t n_ops_lt = ppred ?
Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
const std::size_t len = 2 != finx ? nsrc : nsrc - 1;
if (2 == finx) { // pop_heap special verification
// verify that the maximal element is in
// the end of the sequence: 25.3.6.2, p2
rw_assert (val == xsrc[nsrc - 1].data_.val_, 0, line,
"line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\", last is %#c, expected %#c",
__LINE__, fname, itname, ppred, funname, src,
int (nsrc), -1, xsrc, xsrc [nsrc - 1].data_.val_, val);
}
if (3 == finx) { // sort_heap special verification
// verify that we got a sorted sequence: 25.3.6.4, p1
rw_assert (is_sorted_lt (xsrc, xsrc_end), 0, line,
"line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\" is not sorted",
__LINE__, fname, itname, ppred, funname, src,
int (nsrc), -1, xsrc);
}
else {
// verify that we got a heap:
// 25.3.6.1, p2; 25.3.6.2, p2; 25.3.6.3, p1
rw_assert (is_heap (xsrc, len), 0, line,
"line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\" is not a heap",
__LINE__, fname, itname, ppred, funname, src,
int (len), -1, xsrc);
}
// verify the complexity:
// 25.3.6.1, p3; 25.3.6.2, p3; 25.3.6.3, p2; 25.3.6.4, p2
rw_assert (n_ops_lt <= ops, 0, line,
"line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\" complexity: got %zu invocations of %s, "
"expected no more %zu",
__LINE__, fname, itname, ppred, funname, src,
int (nsrc), -1, xsrc, n_ops_lt,
ppred ? "predicate" : "operator< ()", ops);
delete[] xsrc;
}
/**************************************************************************/
template <class T, class Predicate>
void test_make_heap (const T*,
const Predicate *ppred)
{
rw_info (0, 0, 0,
"std::make_heap (%s, %1$s%{?}, %s%{;})",
"RandomAccessIterator", 0 != ppred, Predicate::name ());
#define TEST(src) \
test_heap_operation (__LINE__, src, (T*)0, ppred, 0)
TEST ("a");
TEST ("ab");
TEST ("ba");
TEST ("abcde");
TEST ("acbed");
TEST ("cbade");
TEST ("debca");
TEST ("ecace");
TEST ("accee");
TEST ("caced");
TEST ("abcdefghij");
TEST ("bcdeafghij");
TEST ("dcbeafihgj");
TEST ("badcfehgji");
TEST ("ebadcfhijg");
TEST ("jihgfedcba");
TEST ("ijhgefdcab");
TEST ("ababababab");
TEST ("babbbababb");
#undef TEST
}
/**************************************************************************/
template <class T, class Predicate>
void test_push_heap (const T*,
const Predicate *ppred)
{
rw_info (0, 0, 0,
"std::push_heap (%s, %1$s%{?}, %s%{;})",
"RandomAccessIterator", 0 != ppred, Predicate::name ());
#define TEST(src) \
test_heap_operation (__LINE__, src, (T*)0, ppred, 1)
TEST ("a");
TEST ("ab");
TEST ("ba");
TEST ("bac");
TEST ("cba");
TEST ("aac");
TEST ("ecdaba");
TEST ("ecdabc");
TEST ("ecdabe");
TEST ("jighefcadj");
TEST ("jighefcada");
TEST ("jighefcadh");
TEST ("jhigcfbeda");
TEST ("jhigcfbedj");
TEST ("jhigcfbedh");
TEST ("jhigcfbedf");
TEST ("jhigcfbede");
TEST ("jhigcfbedg");
TEST ("bbbbbaaaaa");
TEST ("bbbbbaaaab");
#undef TEST
}
/**************************************************************************/
template <class T, class Predicate>
void test_pop_heap (const T*,
const Predicate *ppred)
{
rw_info (0, 0, 0,
"std::pop_heap (%s, %1$s%{?}, %s%{;})",
"RandomAccessIterator", 0 != ppred, Predicate::name ());
#define TEST(src) \
test_heap_operation (__LINE__, src, (T*)0, ppred, 2)
TEST ("a");
TEST ("ba");
TEST ("aaa");
TEST ("cba");
TEST ("caa");
TEST ("ecdab");
TEST ("ecdab");
TEST ("ecdab");
TEST ("jighefcadb");
TEST ("jighcfdbea");
TEST ("jhigcfbeda");
TEST ("jihgfedacb");
TEST ("iihegfabdc");
TEST ("iihgfedcba");
TEST ("iihgefdcab");
TEST ("bbbbbaaaaa");
#undef TEST
}
/**************************************************************************/
template <class T, class Predicate>
void test_sort_heap (const T*,
const Predicate *ppred)
{
rw_info (0, 0, 0,
"std::sort_heap (%s, %1$s%{?}, %s%{;})",
"RandomAccessIterator", 0 != ppred, Predicate::name());
#define TEST(src) \
test_heap_operation (__LINE__, src, (T*)0, ppred, 3)
TEST ("a");
TEST ("ba");
TEST ("aaa");
TEST ("cba");
TEST ("caa");
TEST ("ecdab");
TEST ("ecdab");
TEST ("ecdab");
TEST ("jighefcadb");
TEST ("jighcfdbea");
TEST ("jhigcfbeda");
TEST ("jihgfedacb");
TEST ("iihegfabdc");
TEST ("iihgfedcba");
TEST ("iihgefdcab");
TEST ("bbbbbaaaaa");
#undef TEST
}
/**************************************************************************/
/* extern */ int rw_opt_no_make_heap; // --no-make_heap
/* extern */ int rw_opt_no_push_heap; // --no-push_heap
/* extern */ int rw_opt_no_pop_heap; // --no-pop_heap
/* extern */ int rw_opt_no_sort_heap; // --no-sort_heap
/* extern */ int rw_opt_no_predicate; // --no-predicate
/**************************************************************************/
template <class T, class Predicate>
void test_heap_operations (const T*,
const Predicate *ppred)
{
if (rw_opt_no_make_heap) {
rw_note (0, __FILE__, __LINE__,
"std::make_heap test disabled");
}
else {
test_make_heap ((T*)0, ppred);
}
if (rw_opt_no_push_heap) {
rw_note (0, __FILE__, __LINE__,
"std::push_heap test disabled");
}
else {
test_push_heap ((T*)0, ppred);
}
if (rw_opt_no_pop_heap) {
rw_note (0, __FILE__, __LINE__,
"std::pop_heap test disabled");
}
else {
test_pop_heap ((T*)0, ppred);
}
if (rw_opt_no_sort_heap) {
rw_note (0, __FILE__, __LINE__,
"std::sort_heap test disabled");
}
else {
test_sort_heap ((T*)0, ppred);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_heap_operations ((UserClass*)0, (Less<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"heap operations predicate test disabled");
}
else {
test_heap_operations ((UserClass*)0, (Less<UserClass>*)1);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.heap.operations",
0 /* no comment */, run_test,
"|-no-make_heap#"
"|-no-push_heap#"
"|-no-pop_heap#"
"|-no-sort_heap#"
"|-no-predicate",
&rw_opt_no_make_heap,
&rw_opt_no_push_heap,
&rw_opt_no_pop_heap,
&rw_opt_no_sort_heap,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,339 @@
/***************************************************************************
*
* 25.includes.cpp - test exercising 25.3.5.1 [lib.includes]
*
* $Id: 25.includes.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for includes
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
bool
includes (InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > > );
template
bool
includes (InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > >,
InputIter<lt_comp<base<no_ctor> > >,
binary_predicate<lt_comp<base<no_ctor> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
template
<class T, class InputIterator1, class InputIterator2, class Predicate>
void test_includes (int line,
const char *src1,
const char *src2,
const bool res,
const InputIterator1 &it1,
const InputIterator2 &it2,
const T*,
const Predicate *ppred)
{
const char* const it1name = type_name (it1, (T*)0);
const char* const it2name = type_name (it2, (T*)0);
const char* const fname = "includes";
const char* const predname = Predicate::name();
const std::size_t nsrc1 = std::strlen (src1);
const std::size_t nsrc2 = std::strlen (src2);
T* const xsrc1 = T::from_char (src1, nsrc1);
T* const xsrc2 = T::from_char (src2, nsrc2);
T* const xsrc1_end = xsrc1 + nsrc1;
T* const xsrc2_end = xsrc2 + nsrc2;
const InputIterator1 first1 = make_iter (xsrc1, xsrc1, xsrc1_end, it1);
const InputIterator1 last1 = make_iter (xsrc1_end, xsrc1, xsrc1_end, it1);
const InputIterator2 first2 = make_iter (xsrc2, xsrc2, xsrc2_end, it2);
const InputIterator2 last2 = make_iter (xsrc2_end, xsrc2, xsrc2_end, it2);
const Predicate pred (0, 0);
const std::size_t last_n_op_lt = T::n_total_op_lt_;
const bool result = ppred ?
std::includes (first1, last1, first2, last2, pred)
: std::includes (first1, last1, first2, last2);
// check the returned value
rw_assert (res == result, 0, line,
"line %d: %s<%s, %s%{?}, %s%{;}>(\"%s\", \"%s\", ...) "
"== %b, got %b",
__LINE__, fname, it1name, it2name, ppred, predname, src1, src2,
res, result);
std::size_t n_ops_lt = ppred ?
Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
// check the complexity
std::size_t n_exp_ops = nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s%{?}, %s%{;}>(\"%s\", \"%s\", ...) "
"complexity: got %zu, expected <= %zu",
__LINE__, fname, it1name, it2name, ppred, predname, src1, src2,
n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
}
/**************************************************************************/
template
<class T, class InputIterator1, class InputIterator2, class Predicate>
void test_includes (const InputIterator1 &it1,
const InputIterator2 &it2,
const T*,
const Predicate *ppred)
{
const char* const it1name = type_name (it1, (T*)0);
const char* const it2name = type_name (it2, (T*)0);
const char* const fname = "includes";
const char* const predname = Predicate::name ();
rw_info (0, 0, 0,
"std::%s(%s, %2$s, %s, %3$s%{?}, %s%{;})",
fname, it1name, it2name, ppred, predname);
#define TEST(src1, src2, res) \
test_includes (__LINE__, src1, src2, res, it1, it2, (T*)0, ppred)
TEST ("", "", true);
TEST ("a", "", true);
TEST ("", "a", false);
TEST ("a", "a", true);
TEST ("a", "b", false);
TEST ("b", "a", false);
TEST ("aa", "aa", true);
TEST ("aa", "ab", false);
TEST ("ab", "aa", false);
TEST ("ab", "ab", true);
TEST ("abcdef", "b", true);
TEST ("abcdef", "bd", true);
TEST ("abcdef", "i", false);
TEST ("abcdef", "ei", false);
TEST ("abcde", "abcde", true);
TEST ("abbde", "abbde", true);
TEST ("abcce", "abcce", true);
TEST ("abcdd", "abcdd", true);
TEST ("ab", "aaabbbb", false);
TEST ("ab", "aaabbbc", false);
TEST ("aaabbbb", "ab", true);
TEST ("aaabbbc", "ac", true);
TEST ("a", "aaaaaaaa", false);
TEST ("a", "aaaaaaab", false);
TEST ("aaaaaaaa", "aaaaaaaa", true);
TEST ("aaaaaaab", "aaaaaaab", true);
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T, class InputIterator1, class Predicate>
void test_includes (const InputIterator1 &it1,
const T*,
const Predicate *ppred)
{
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_includes (it1, input_iter, (T*)0, ppred);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_includes (it1, fwd_iter, (T*)0, ppred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_includes (it1, bidir_iter, (T*)0, ppred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_includes (it1, rand_iter, (T*)0, ppred);
}
}
/**************************************************************************/
template <class T, class Predicate>
void test_includes (const T*,
const Predicate *ppred)
{
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0,
"template <class %s, class %s%{?}, class %s%{;}> "
"bool std::includes (%1$s, %1$s, %2$s, %2$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", ppred, "Compare",
ppred, "Compare");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_includes (input_iter, (T*)0, ppred);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_includes (fwd_iter, (T*)0, ppred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_includes (bidir_iter, (T*)0, ppred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_includes (rand_iter, (T*)0, ppred);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_includes ((UserClass*)0, (Less<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::includes predicate test disabled");
}
else {
test_includes ((UserClass*)0, (Less<UserClass>*)1);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.includes",
0 /* no comment */,
run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,334 @@
/***************************************************************************
*
* 25.lex.comparison.cpp - test exercising 25.3.8 [lib.lex.comparison]
*
* $Id: 25.lex.comparison.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for lexicographical_compare
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
// explicitly instantiate on types with minimum features
// to verify that the algorithm imposes no requirements
// beyond those specified
template
bool lexicographical_compare (InputIter<lt_comp<base<> > >,
InputIter<lt_comp<base<> > >,
InputIter<lt_comp<base<> > >,
InputIter<lt_comp<base<> > >);
template
bool lexicographical_compare (InputIter<base<> >,
InputIter<base<> >,
InputIter<base<> >,
InputIter<base<> >,
binary_predicate<base<> >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
// exercise lexicographical_compare 25.3.8
template
<class T, class InputIterator1, class InputIterator2, class Predicate>
void test_lex_compare (int line,
const char *src1,
const char *src2,
bool res,
const InputIterator1 &it1,
const InputIterator2 &it2,
const T*,
const Predicate *ppred)
{
const char* const it1name = type_name (it1, (T*)0);
const char* const it2name = type_name (it2, (T*)0);
const char* const fname = "lexicographical_compare";
const char* const funname = Predicate::name ();
const std::size_t nsrc1 = std::strlen (src1);
const std::size_t nsrc2 = std::strlen (src2);
T* const xsrc1 = T::from_char (src1, nsrc1);
T* const xsrc2 = T::from_char (src2, nsrc2);
T* const xsrc1_end = xsrc1 + nsrc1;
T* const xsrc2_end = xsrc2 + nsrc2;
const InputIterator1 first1 = make_iter (xsrc1, xsrc1, xsrc1_end, it1);
const InputIterator1 last1 = make_iter (xsrc1_end, xsrc1, xsrc1_end, it1);
const InputIterator2 first2 = make_iter (xsrc2, xsrc2, xsrc2_end, it2);
const InputIterator2 last2 = make_iter (xsrc2_end, xsrc2, xsrc2_end, it2);
const Predicate pred (0, 0);
const std::size_t last_n_op_lt = T::n_total_op_lt_;
const bool result = ppred ?
std::lexicographical_compare (first1, last1, first2, last2, pred)
: std::lexicographical_compare (first1, last1, first2, last2);
// verify the returned value 25.3.8, p1 and p3: If two sequences have
// the same number of elements and their corresponding elements are
// equivalent, then neither sequence is lexicographically less than
// the other.
rw_assert (res == result, 0, line,
"line %d: %s<%s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"== %b, got %b",
__LINE__, fname, it1name, it2name, 0 != ppred, funname,
src1, src2, res, result);
const std::size_t n_ops_lt = ppred ?
Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
// verify the complexity 25.3.8, p2
const std::size_t n_exp_ops = 2 * (nsrc1 < nsrc2 ? nsrc1 : nsrc2);
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"complexity: got %zu, expected no more than %zu",
__LINE__, fname, it1name, it2name, 0 != ppred, funname,
src1, src2, n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
}
template
<class T, class InputIterator1, class InputIterator2, class Predicate>
void test_lex_compare (const InputIterator1 &it1,
const InputIterator2 &it2,
const T*,
const Predicate *ppred)
{
const char* const it1name = type_name (it1, (T*)0);
const char* const it2name = type_name (it2, (T*)0);
const char* const fname = "lexicographical_compare";
const char* const funname = Predicate::name();
rw_info (0, 0, 0,
"std::%s(%s, %2$s, %s, %3$s%{?}, %s%{;})",
fname, it1name, it2name, 0 != ppred, funname);
#define TEST(src1, src2, res) \
test_lex_compare (__LINE__, src1, src2, res, it1, it2, (T*)0, ppred)
TEST ("", "", false);
TEST ("a", "", false);
TEST ("", "a", true);
TEST ("a", "a", false);
TEST ("aa", "aa", false);
TEST ("aa", "ab", true);
TEST ("ba", "ab", false);
TEST ("ba", "ba", false);
TEST ("ba", "bc", true);
TEST ("a", "abc", true);
TEST ("a", "bcd", true);
TEST ("a", "baed", true);
TEST ("abcde", "abcdefghij", true);
TEST ("fghij", "fghijabcde", true);
TEST ("fghij", "abcdefghij", false);
TEST ("cabed", "abcdeabcde", false);
TEST ("abcdefghij", "abcdefghij", false);
TEST ("fghijfghij", "abcdefghij", false);
TEST ("fghijabcde", "abcdeabcde", false);
TEST ("abcdefghij", "bacdfeghji", true);
TEST ("bacdefghij", "bacdfeghji", true);
TEST ("bacdfeghij", "bacdfeghji", true);
TEST ("bacdfeghja", "bacdfeghji", true);
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T, class InputIterator1, class Predicate>
void test_lex_compare (const InputIterator1 &it1,
const T*,
const Predicate *ppred)
{
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_lex_compare (it1, input_iter, (T*)0, ppred);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_lex_compare (it1, fwd_iter, (T*)0, ppred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_lex_compare (it1, bidir_iter, (T*)0, ppred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_lex_compare (it1, rand_iter, (T*)0, ppred);
}
}
template <class T, class Predicate>
void test_lex_compare (const T*,
const Predicate *ppred)
{
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0,
"template <class %s, class %s%{?}, class %s%{;}> "
"bool std::lexicographical_compare (%1$s, %1$s, %2$s, "
"%2$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", ppred, "Compare",
0 != ppred, "Compare");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_lex_compare (input_iter, (T*)0, ppred);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_lex_compare (fwd_iter, (T*)0, ppred);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_lex_compare (bidir_iter, (T*)0, ppred);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_lex_compare (rand_iter, (T*)0, ppred);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_lex_compare ((UserClass*)0, (Less<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::lexicographical_compare predicate test disabled");
}
else {
test_lex_compare ((UserClass*)0, (Less<UserClass>*)1);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.lex.comparison",
0 /* no comment */,
run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,420 @@
/***************************************************************************
*
* 25.libc.cpp - test exercising 25.4 [lib.alg.c.library]
*
* $Id: 25.libc.cpp 510970 2007-02-23 14:57:45Z 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.
*
***************************************************************************/
#include <cstdlib> // for bsearch, qsort
#include <csignal> // for signal
#include <csetjmp> // for setjmp, longjmp
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
// used as a special value in comp below
static int global[] = { 0, 0 };
extern "C" {
static std::jmp_buf jmp_env;
// SIGABRT handler
static void handle_ABRT (int)
{
// jump outta here to prevent abort() from trying too hard...
std::longjmp (jmp_env, 1);
}
static int c_comp (const void *x, const void *y)
{
#ifndef _RWSTD_NO_EXCEPTIONS
// verify that a thrown exception can be caught
if (x >= global && x < global + sizeof global / sizeof *global)
throw x;
#endif // _RWSTD_NO_EXCEPTIONS
return (*_RWSTD_STATIC_CAST (const UserClass*, x)).data_.val_
- (*_RWSTD_STATIC_CAST (const UserClass*, y)).data_.val_;
}
}
extern "C++" {
static int cxx_comp (const void *x, const void *y)
{
#ifndef _RWSTD_NO_EXCEPTIONS
// verify that a thrown exception can be caught
if (x >= global && x < global + sizeof global / sizeof *global)
throw x;
#endif // _RWSTD_NO_EXCEPTIONS
return (*_RWSTD_STATIC_CAST (const UserClass*, x)).data_.val_
- (*_RWSTD_STATIC_CAST (const UserClass*, y)).data_.val_;
}
}
/**************************************************************************/
// exrcises std::qqsort (25.4.4)
static void
test_qsort (int line,
const char *src,
std::size_t nsrc,
bool cxx)
{
UserClass* const xsrc = UserClass::from_char (src, nsrc);
UserClass* const xsrc_end = xsrc + nsrc;
RW_ASSERT (0 == nsrc || 0 != xsrc);
if (cxx)
std::qsort (xsrc, nsrc, sizeof *xsrc, cxx_comp);
else
std::qsort (xsrc, nsrc, sizeof *xsrc, c_comp);
bool success = is_sorted_lt (xsrc, xsrc_end);
rw_assert (success, 0, line,
"line %d: extern \"C%{?}++%{;}\" qsort (\"%s\", ...) ==> "
"\"%{X=*.*}\" not sorted",
__LINE__, cxx, src, int (nsrc), -1, xsrc);
delete[] xsrc;
}
/**************************************************************************/
// exrcises std::qsort (25.4.4 Note)
static void
test_qsort_exception (int line,
int *src,
std::size_t nsrc,
bool cxx)
{
#ifndef _RWSTD_NO_EXCEPTIONS
// install a SIGABRT handler in case libc can't throw
// exceptions and aborts instead (e.g., glibc/gcc)
std::signal (SIGABRT, handle_ABRT);
bool success = false;
try {
if (0 == setjmp (jmp_env)) {
if (cxx)
std::qsort (src, nsrc, sizeof *src, cxx_comp);
else
std::qsort (src, nsrc, sizeof *src, c_comp);
}
else {
// prevent double assertion
success = true;
rw_assert (false, 0, line,
"line %d: extern \"C%{?}++%{;}\" qsort() aborted "
"on exception", __LINE__, cxx);
}
}
catch (const void* x) {
success = x >= src && x < src + nsrc;
}
catch (...) {
}
rw_assert (success, 0, line,
"line %d: extern \"C%{?}++%{;}\" qsort() failed to propagate "
"exception", __LINE__, cxx);
#else // if defined (_RWSTD_NO_EXCEPTIONS)
_RWSTD_UNUSED (line);
_RWSTD_UNUSED (src);
_RWSTD_UNUSED (nsrc);
_RWSTD_UNUSED (key);
_RWSTD_UNUSED (cxx);
#endif // _RWSTD_NO_EXCEPTIONS
}
/**************************************************************************/
// exrcises std::bsearch (25.4.3)
static void
test_bsearch (int line,
const char *src,
std::size_t nsrc,
const char key_val,
std::size_t res,
bool cxx)
{
UserClass* const xsrc = UserClass::from_char (src, nsrc,
true); // must be sorted
RW_ASSERT (0 == nsrc || 0 != xsrc);
UserClass key;
key.data_.val_ = key_val;
const void* result = cxx ?
std::bsearch (&key, xsrc, nsrc, sizeof *xsrc, cxx_comp)
: std::bsearch (&key, xsrc, nsrc, sizeof *xsrc, c_comp);
const UserClass* exp_res = res == _RWSTD_SIZE_MAX ? 0 : xsrc + res;
bool success = result == exp_res;
rw_assert (success, 0, line,
"line %d: extern \"C%{?}++%{;}\" bsearch (\"%s\", %#c, ...) "
"== %p, got %p, difference is %td elements",
__LINE__, cxx, src, key_val, result, exp_res,
_RWSTD_STATIC_CAST (const UserClass*, result) - exp_res);
delete[] xsrc;
}
/**************************************************************************/
// exrcises std::bsearch (25.4.4 Note)
static void
test_bsearch_exception (int line,
const int *src,
std::size_t nsrc,
const int *key,
bool cxx)
{
#ifndef _RWSTD_NO_EXCEPTIONS
// install a SIGABRT handler in case libc can't throw
// exceptions and aborts instead (e.g., glibc/gcc)
std::signal (SIGABRT, handle_ABRT);
bool success = false;
try {
if (0 == setjmp (jmp_env)) {
if (cxx)
std::bsearch (key, src, nsrc, sizeof *src, cxx_comp);
else
std::bsearch (key, src, nsrc, sizeof *src, c_comp);
}
else {
// prevent double assertion
success = true;
rw_assert (false, 0, line,
"line %d: extern \"C%{?}++%{;}\" bsearch() aborted "
"on exception", __LINE__, cxx);
}
}
catch (const void* x) {
success = x >= src && x < src + nsrc;
}
catch (...) {
}
rw_assert (success, 0, line,
"line %d: extern \"C%{?}++%{;}\" bsearch() failed to propagate "
"exception", __LINE__, cxx);
#else // if defined (_RWSTD_NO_EXCEPTIONS)
_RWSTD_UNUSED (line);
_RWSTD_UNUSED (src);
_RWSTD_UNUSED (nsrc);
_RWSTD_UNUSED (key);
_RWSTD_UNUSED (cxx);
#endif // _RWSTD_NO_EXCEPTIONS
}
/**************************************************************************/
static int rw_opt_no_c; // --no-c
static int rw_opt_no_cxx; // --no-cpp
static int rw_opt_no_bsearch; // --no-bsearch
static int rw_opt_no_qsort; // --no-qsort
static int rw_opt_no_exceptions; // --no-exceptions
/**************************************************************************/
static void
test_qsort (bool cxx)
{
rw_info (0, 0, 0,
"extern \"C%{?}++%{;}\" qsort (void*, size_t, size_t, "
"int (*compar)(const void*, const void*))", cxx);
#define TEST(src) \
test_qsort (__LINE__, src, sizeof src - 1, cxx)
TEST ("a");
TEST ("ba");
TEST ("cba");
TEST ("dcba");
TEST ("edcba");
TEST ("fedcba");
TEST ("gfedcba");
TEST ("hgfedcba");
TEST ("ihgfedcba");
TEST ("jihgfedcba");
TEST ("ab");
TEST ("abc");
TEST ("abcd");
TEST ("abcde");
TEST ("abcdef");
TEST ("abcdefg");
TEST ("abcdefgh");
TEST ("abcdefghi");
TEST ("abcdefghij");
TEST ("aa");
TEST ("aabb");
TEST ("bbccaa");
TEST ("ddbbccaa");
TEST ("ddeebbccaa");
TEST ("aaaaaaaaaa");
TEST ("ababababab");
TEST ("bababababa");
#undef TEST
if (rw_opt_no_exceptions) {
rw_note (0, 0, 0, "extern \"C%{?}++%{;}\" qsort() exceptions tests "
"disabled", cxx);
}
else {
test_qsort_exception (__LINE__, global,
sizeof global / sizeof *global, cxx);
}
}
/**************************************************************************/
static void
test_bsearch (bool cxx)
{
rw_info (0, 0, 0,
"extern \"C%{?}++%{;}\" bsearch (const void*, const void*, "
"size_t, size_t, int (*compar)(const void*, const void*))",
cxx);
#define TEST(src, key, res) \
test_bsearch (__LINE__, src, sizeof src - 1, key, \
std::size_t (res), cxx)
TEST ("", 'a', -1);
TEST ("a", 'a', 0);
TEST ("a", 'b', -1);
TEST ("b", 'a', -1);
TEST ("ab", 'a', 0);
TEST ("ac", 'a', 0);
TEST ("ab", 'b', 1);
TEST ("bc", 'a', -1);
TEST ("acegi", 'i', 4);
TEST ("acegi", 'b', -1);
TEST ("acegi", 'g', 3);
TEST ("acegi", 'f', -1);
TEST ("acegi", 'e', 2);
TEST ("acegi", 'j', -1);
TEST ("acegi", 'c', 1);
TEST ("bdfhj", 'a', -1);
TEST ("abcdefghij", 'a', 0);
TEST ("abcdefghij", 'c', 2);
TEST ("abcdefghij", 'f', 5);
TEST ("abcdefghij", 'h', 7);
TEST ("abcdefghij", 'j', 9);
#undef TEST
if (rw_opt_no_exceptions) {
rw_note (0, 0, 0, "extern \"C%{?}++%{;}\" bsearch() exceptions "
"tests disabled", cxx);
}
else {
test_bsearch_exception (__LINE__, global,
sizeof global / sizeof *global, global, cxx);
}
}
/**************************************************************************/
static void
test_libc (bool cxx)
{
if (rw_opt_no_qsort)
rw_note (0, 0, 0, "qsort test disabled");
else
test_qsort (cxx);
if (rw_opt_no_bsearch)
rw_note (0, 0, 0, "bsearch test disabled");
else
test_bsearch (cxx);
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_c)
rw_note (0, 0, 0, "tests of extern \"C\" cfunctions disabled");
else
test_libc (false);
if (rw_opt_no_cxx)
rw_note (0, 0, 0, "tests of extern \"C++\" functions disabled");
else
test_libc (true);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.c.library",
0 /* no comment */,
run_test,
"|-no-extern_c# "
"|-no-extern_cxx# "
"|-no-bsearch# "
"|-no-qsort# "
"|-no-exceptions",
&rw_opt_no_c,
&rw_opt_no_cxx,
&rw_opt_no_bsearch,
&rw_opt_no_qsort,
&rw_opt_no_exceptions);
}

View File

@@ -0,0 +1,286 @@
/***************************************************************************
*
* 25.lower.bound.cpp - test exercising 25.3.3.1 [lib.lower.bound]
*
* $Id: 25.lower.bound.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <rw/_config.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// disable implicit inclusion to work around a limitation
// of IBM VisualAge 5.0 (see PR #26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#include <algorithm>
#include <cstring>
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h>
/**************************************************************************/
// distinct and not Less-Than-Comparable with class UserClass (except as
// defined below) to detect unwarranted assumptions made by the
// implementation of the algorithms
struct Y
{
UserClass xval_;
// not Default-Constructible
Y (int /* dummy */, int /*dummy */): xval_ () { }
// CopyConstructible
Y (const Y &rhs): xval_ (rhs.xval_) { }
private:
void operator=(Y&); // not Assignable
};
inline conv_to_bool
operator< (const UserClass &lhs, const Y &rhs)
{
return conv_to_bool::make (lhs < rhs.xval_);
}
/**************************************************************************/
// predicate used as the Compare argument to lower_bound()
struct LessThan
{
static std::size_t funcalls_;
LessThan (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &lhs, const Y &rhs) {
++funcalls_;
return conv_to_bool::make (lhs < rhs.xval_);
}
private:
void operator= (LessThan&); // not assignable
};
std::size_t LessThan::funcalls_;
/**************************************************************************/
template <class ForwardIterator>
void test_lower_bound (int line,
const char *src_str,
char val_char,
std::size_t result_off,
std::size_t ncomp,
const ForwardIterator*,
const char *itname,
bool predicate)
{
RW_ASSERT (0 != src_str);
const std::size_t nsrc = std::strlen (src_str);
UserClass* const xsrc = UserClass::from_char (src_str, nsrc);
if (nsrc < result_off)
result_off = nsrc;
// construct the source range to pass to the algorithm
const ForwardIterator first (xsrc, xsrc, xsrc + nsrc);
const ForwardIterator last (xsrc + nsrc, xsrc + nsrc, xsrc + nsrc);
// construct the object to pass to the algorithm
// the type of the object is distinct from the iterator's value_type
// to detect unwarranted assumptions made by the implementation
Y value (0, 0 /* dummy arguments */);
value.xval_.data_.val_ = val_char;
// construct the Compare function object to pass to the algorithm
// when `predicate' is true
const LessThan comp (0, 0 /* dummy arguments */);
// reset the counter of invocations of UserClass::operator<()
UserClass::n_total_op_lt_ = 0;
// invoke the appropriate form of the algorithm, storing
// the resturned value
const ForwardIterator result = predicate
? std::lower_bound (first, last, value, comp)
: std::lower_bound (first, last, value);
// silence bogus EDG eccp 3.6 remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (result);
// verify correctness
const std::size_t off = std::size_t (result.cur_ - xsrc);
rw_assert (off == result_off, 0, line,
"lower_bound(%s = \"%s\", ...%{?}%#c%{;}) ==> "
"first + %zu, got %zu",
itname, src_str, !predicate, val_char,
off, result_off);
// verify complexity
const std::size_t funcalls = predicate
? LessThan::funcalls_ : UserClass::n_total_op_lt_;
rw_assert (funcalls <= ncomp, 0, line,
"lower_bound(%s = \"%s\", ...%{?}%#c%{;}) complexity: "
"invoked predicate at most %zu times, got %zu",
itname, src_str, !predicate, val_char,
ncomp, funcalls);
delete[] xsrc;
}
/**************************************************************************/
template <class ForwardIterator>
void test_lower_bound (const ForwardIterator*,
const char *itname,
bool predicate)
{
#define TEST(str, val, off, comp) \
test_lower_bound (__LINE__, str, val, std::size_t (off), \
std::size_t (comp), (ForwardIterator*)0, \
itname, predicate)
rw_info (0, 0, 0,
"std::lower_bound (%s, %1$s, const UserClass&%{?}, %s%{;})",
itname, predicate, "LessThan");
// +--------------- source sequence
// | +--------- value argument
// | | +----- offset of the resturned iterator, -1 for end
// | | | +-- complexity: at most (log(last - first) + 1)
// | | | | comparisons (or applications of the predicate)
// | | | |
// V V V V
TEST ("", 'a', 0, 0);
TEST ("a", 'a', 0, 1);
TEST ("a", 'b', 1, 1);
TEST ("b", 'a', 0, 1);
TEST ("aa", 'a', 0, 2);
TEST ("ab", 'a', 0, 2);
TEST ("ab", 'b', 1, 2);
TEST ("bb", 'a', 0, 2);
TEST ("ace", 'a', 0, 3);
TEST ("ace", 'b', 1, 3);
TEST ("ace", 'c', 1, 3);
TEST ("ace", 'd', 2, 3);
TEST ("ace", 'e', 2, 3);
TEST ("ace", 'f', 3, 3);
TEST ("aceg", 'a', 0, 3);
TEST ("aceg", 'b', 1, 3);
TEST ("aceg", 'c', 1, 3);
TEST ("aceg", 'd', 2, 3);
TEST ("aceg", 'e', 2, 3);
TEST ("aceg", 'f', 3, 3);
TEST ("aceg", 'g', 3, 3);
TEST ("aceg", 'h', 4, 3);
}
/**************************************************************************/
static int rw_opt_no_fwd_iter;
static int rw_opt_no_bidir_iter;
static int rw_opt_no_rnd_iter;
static int rw_opt_no_predicate;
static void
test_lower_bound (bool predicate)
{
rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
"std::lower_bound (%1$s, %1$s, const UserClass&%{?}, %4$s%{;})",
"ForwardIterator", "UserClass", predicate, "Compare", predicate);
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "ForwardIterator test disabled");
}
else {
test_lower_bound ((FwdIter<UserClass>*)0, "ForwardIterator", predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
}
else {
test_lower_bound ((BidirIter<UserClass>*)0, "BidirectionalIterator",
predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
}
else {
test_lower_bound ((RandomAccessIter<UserClass>*)0,
"RandomAccessIterator", predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_lower_bound (false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"test of the Predicate form of std::lower_bound disabled");
}
else {
test_lower_bound (true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.lower.bound",
0 /* no comment */,
run_test,
"|-no-Predicate# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,576 @@
/***************************************************************************
*
* 25.merge.cpp - test exercising 25.3.4 [lib.alg.merge]
*
* $Id: 25.merge.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for merge,
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
merge (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
merge (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
template
void
inplace_merge (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
inplace_merge (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &x,
const UserClass &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
private:
void operator= (Less&); // not assignable
};
std::size_t Less::funcalls_;
/**************************************************************************/
// ordinary (non-template) base to minimize code bloat
struct MergeBase
{
const char* iter_names [3];
virtual ~MergeBase () { }
// invokes inplace_merge with iterators initialized
// to the specified arguments and (optionally) with
// a predicate object
virtual void
inplace_merge (UserClass*, UserClass*, UserClass*, const Less*) const {
RW_ASSERT (!"test logic error");
}
// invokes merge
virtual UserClass*
merge (const UserClass*, const UserClass*, const UserClass*,
const UserClass*, UserClass*, UserClass*, const Less*) const {
RW_ASSERT (!"test logic error");
return 0;
}
};
template <class InputIterator1, class InputIterator2, class OutputIterator>
struct Merge: MergeBase
{
Merge () {
iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
}
virtual UserClass*
merge (const UserClass *xsrc1, const UserClass *xsrc1_end,
const UserClass *xsrc2, const UserClass *xsrc2_end,
UserClass *xdst, UserClass *xdst_end,
const Less *ppred) const {
const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
const OutputIterator result (xdst, xdst, xdst_end);
const OutputIterator ret = ppred ?
std::merge (first1, last1, first2, last2, result, *ppred)
: std::merge (first1, last1, first2, last2, result);
// silence EDG eccp 3.7 and prior remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (ret);
return ret.cur_;
}
};
template <class BidirectionalIterator>
struct InplaceMerge: MergeBase
{
InplaceMerge () {
iter_names [0] = type_name (BidirectionalIterator (0, 0, 0),
(UserClass*)0);
iter_names [1] = 0;
iter_names [2] = 0;
}
virtual void
inplace_merge (UserClass *xsrc, UserClass *xsrc_mid, UserClass *xsrc_end,
const Less *ppred) const {
const BidirectionalIterator first (xsrc, xsrc, xsrc_end);
const BidirectionalIterator mid (xsrc_mid, xsrc, xsrc_end);
const BidirectionalIterator last (xsrc_end, xsrc, xsrc_end);
if (ppred)
std::inplace_merge (first, mid, last, *ppred);
else
std::inplace_merge (first, mid, last);
}
};
/**************************************************************************/
// ordinary (non-template) function to minimize code bloat
void test_merge (int line,
const char *src1,
const char *src2,
const std::size_t midinx,
bool predicate,
const MergeBase &alg)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const predname = predicate ? "Less" : 0;
const bool inplace = 0 == it2name;
const char* const algname = inplace ? "inplace_merge" : "merge";
const std::size_t nsrc1 = std::strlen (src1);
const std::size_t nsrc2 = std::strlen (src2);
UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1);
UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2);
const std::size_t ndst = nsrc1 + nsrc2;
UserClass* const xdst = inplace ? xsrc1 : new UserClass [ndst];
UserClass* const xsrc1_end = xsrc1 + nsrc1;
UserClass* const xsrc2_end = xsrc2 + nsrc2;
UserClass* const xsrc_mid = xsrc1 + midinx;
UserClass* const xdst_end = xdst + ndst;
const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
const Less pred (0, 0);
const Less* const ppred = predicate ? &pred : 0;
UserClass* xdst_res = 0;
if (inplace) { // inplace_merge
alg.inplace_merge (xsrc1, xsrc_mid, xsrc1_end, ppred);
}
else {
xdst_res = alg.merge (xsrc1, xsrc1_end,
xsrc2, xsrc2_end, xdst, xdst_end, ppred);
}
const std::size_t n_ops_lt = ppred ?
Less::funcalls_ : UserClass::n_total_op_lt_ - last_n_op_lt;
bool success = true;
// check output iterator for merge
if (!inplace) {
success = xdst_res == xdst_end;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
" == first + %zu, got first + %td",
__LINE__, algname, it1name, it2name, outname, predicate,
predname, src1, src2, ndst, xdst_res - xdst);
}
// check that the sequence is sorted
success = is_sorted_lt (xdst, xdst_end);
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
"(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
"not sorted",
__LINE__, algname, it1name, !inplace, it2name, outname,
predicate, predname, src1, !inplace, src2, inplace, midinx,
int (ndst), -1, xdst);
// check that the algorithm is stable
std::size_t i = 1;
for ( ; i < ndst; i++) {
if (xdst [i - 1].data_.val_ == xdst [i].data_.val_) {
success = xdst [i - 1].origin_ < xdst [i].origin_;
if (!success)
break;
}
}
// to avoid errors in --trace mode
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
"(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
"not stable at %zu: got ids %d != %d for values %#c == %#c",
__LINE__, algname, it1name, !inplace, it2name, outname,
predicate, predname, src1, !inplace, src2, inplace, midinx,
int (ndst), i, xdst, i, xdst [i - 1].origin_,
xdst [i].origin_, xdst [i - 1].data_.val_, xdst [i].data_.val_);
// check the complexity
success = n_ops_lt <= ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
"(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
"complexity: got %zu, expected <= %zu",
__LINE__, algname, it1name, !inplace, it2name, outname,
predicate, predname, src1, !inplace, src2, inplace, midinx,
int (ndst), -1, xdst, n_ops_lt, ndst - 1);
delete[] xsrc1;
delete[] xsrc2;
if (!inplace)
delete[] xdst;
}
/**************************************************************************/
void test_merge (const MergeBase &alg, bool predicate)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const predname = predicate ? "Less" : 0;
const char* const algname = it2name ? "merge" : "inplace_merge";
rw_info (0, 0, 0,
"%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
outname, algname, it1name, it2name, predicate, predname);
#define TEST(src1, src2) \
test_merge (__LINE__, src1, src2, 0, predicate, alg)
TEST ("ab", "");
TEST ("", "ab");
TEST ("a", "b");
TEST ("b", "a");
TEST ("aa", "bb");
TEST ("bb", "aa");
TEST ("acegi", "bdfhj");
TEST ("aaegi", "bdfjj");
TEST ("accgi", "bdhhj");
TEST ("aceei", "bffhj");
TEST ("acegg", "ddfhj");
TEST ("aceii", "bbfhj");
TEST ("bdfhj", "acegi");
TEST ("bdfjj", "aaegi");
TEST ("bdhhj", "accgi");
TEST ("bffhj", "aceei");
TEST ("ddfhj", "acegg");
TEST ("bbfhj", "aceii");
TEST ("abcde", "abcde");
TEST ("aacde", "aacde");
TEST ("abbde", "abbde");
TEST ("abcce", "abcce");
TEST ("abcdd", "abcdd");
TEST ("abcee", "abcee");
TEST ("aaegi", "bdfjj");
TEST ("accgi", "bdhhj");
TEST ("aceei", "bffhj");
TEST ("acegg", "ddfhj");
TEST ("aceii", "bbfhj");
TEST ("a","abcdefghij");
TEST ("ac","abcdefghi");
TEST ("ace","abcdefgh");
TEST ("aceg","abcdefg");
TEST ("j","abcdefghjj");
TEST ("gj","abcdeggjj");
TEST ("egj","abeeggjj");
TEST ("abcdefghij","a");
TEST ("abcdefghi","ac");
TEST ("abcdefgh","ace");
TEST ("abcdefg","aceg");
TEST ("abcdefghjj","j");
TEST ("abcdeggjj","gj");
TEST ("abeeggjj","egj");
TEST ("aaaaa", "aaaaa");
TEST ("bbbbb", "bbbbb");
}
/**************************************************************************/
void test_inplace_merge (const MergeBase &alg, bool predicate)
{
const char* const itname = alg.iter_names [0];
const char* const predname = predicate ? "Less" : 0;
const char* const algname = alg.iter_names [1] ?
"merge" : "inplace_merge";
rw_info (0, 0, 0, "std::%s(%s, %2$s, %2$s%{?}, %s%{;})",
algname, itname, predicate, predname);
#undef TEST
#define TEST(src, mid) \
test_merge (__LINE__, src, "", mid, predicate, alg)
TEST ("a", 0);
TEST ("aa", 0);
TEST ("a", 1);
TEST ("aa", 2);
TEST ("aa", 1);
TEST ("ab", 1);
TEST ("ba", 1);
TEST ("abcdefghij", 5);
TEST ("aacdeffhij", 5);
TEST ("abbdefggij", 5);
TEST ("abccefghhj", 5);
TEST ("abcddfghii", 5);
TEST ("abceefghjj", 5);
TEST ("abcdeabcde", 5);
TEST ("aacdeaacde", 5);
TEST ("abbdeabbde", 5);
TEST ("abcceabcce", 5);
TEST ("abcddabcdd", 5);
TEST ("abceeabcee", 5);
TEST ("aabcdefghi", 1);
TEST ("aaacdefghi", 1);
TEST ("babcdefghi", 1);
TEST ("babbdefghi", 1);
TEST ("abcdefghia", 9);
TEST ("aacdefghia", 9);
TEST ("abcdefghib", 9);
TEST ("abbdefghib", 9);
}
/**************************************************************************/
/* extern */ int rw_opt_no_merge; // --no-merge
/* extern */ int rw_opt_no_inplace_merge; // --no-inplace_merge
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator1, class InputIterator2, class OutputIterator>
void gen_merge_test (const InputIterator1&,
const InputIterator2&,
const OutputIterator&,
bool predicate)
{
const Merge<InputIterator1, InputIterator2, OutputIterator> alg;
test_merge (alg, predicate);
}
template <class InputIterator1, class InputIterator2>
void gen_merge_test (const InputIterator1 &it1,
const InputIterator2 &it2,
bool predicate)
{
if (0 == rw_opt_no_output_iter)
gen_merge_test (it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_merge_test (it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_merge_test (it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_merge_test (it1, it2, RandomAccessIter<UserClass>(0, 0, 0),
predicate);
}
template <class InputIterator1>
void gen_merge_test (const InputIterator1 &it1, bool predicate)
{
if (0 == rw_opt_no_input_iter)
gen_merge_test (it1, InputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_merge_test (it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_merge_test (it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_merge_test (it1, ConstRandomAccessIter<UserClass>(0, 0, 0),
predicate);
}
// generates a specialization of the merge test for each of the required
// iterator categopries
void gen_merge_test (bool predicate)
{
if (rw_opt_no_input_iter)
rw_note (0, 0, 0, "InputIterator test disabled");
else
gen_merge_test (InputIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_fwd_iter)
rw_note (0, 0, 0, "ForwardIterator test disabled");
else
gen_merge_test (ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_merge_test (ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_merge_test (ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
/**************************************************************************/
template <class BidirectionalIterator>
void gen_inplace_merge_test (const BidirectionalIterator&, bool predicate)
{
const InplaceMerge<BidirectionalIterator> alg;
test_inplace_merge (alg, predicate);
}
/**************************************************************************/
static int run_test (int, char*[])
{
if (rw_opt_no_predicate)
rw_note (0, 0, 0, "predicate test disabled");
const int niters = rw_opt_no_predicate ? 1 : 2;
//////////////////////////////////////////////////////////////////
if (rw_opt_no_merge)
rw_note (0, 0, 0, "merge test disabled");
else {
for (int i = 0; i != niters; ++i) {
gen_merge_test (1 == i);
}
}
//////////////////////////////////////////////////////////////////
if (rw_opt_no_inplace_merge) {
rw_note (0, 0, 0, "inplace_merge test disabled");
}
else {
for (int i = 0; i != niters; ++i) {
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_inplace_merge_test (BidirIter<UserClass> (0, 0, 0), 1 == i);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_inplace_merge_test (RandomAccessIter<UserClass> (0, 0, 0),
1 == i);
}
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.merge",
0 /* no comment */,
run_test,
"|-no-merge# "
"|-no-inplace_merge# "
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_merge,
&rw_opt_no_inplace_merge,
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,425 @@
/***************************************************************************
*
* 25.min.max.cpp - test exercising 25.3.7 [lib.alg.min.max]
*
* $Id: 25.min.max.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for min, max, min_element, max_element
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
const lt_comp<base<cpy_ctor> >&
min (const lt_comp<base<cpy_ctor> >&,
const lt_comp<base<cpy_ctor> >&);
template
const lt_comp<base<cpy_ctor> >&
min (const lt_comp<base<cpy_ctor> >&,
const lt_comp<base<cpy_ctor> >&,
binary_predicate<lt_comp<base<cpy_ctor> > >);
template
const lt_comp<base<cpy_ctor> >&
max (const lt_comp<base<cpy_ctor> >&,
const lt_comp<base<cpy_ctor> >&);
template
const lt_comp<base<cpy_ctor> >&
max (const lt_comp<base<cpy_ctor> >&,
const lt_comp<base<cpy_ctor> >&,
binary_predicate<lt_comp<base<cpy_ctor> > >);
template
FwdIter<lt_comp<base<cpy_ctor> > >
min_element (FwdIter<lt_comp<base<cpy_ctor> > >,
FwdIter<lt_comp<base<cpy_ctor> > >);
template
FwdIter<lt_comp<base<cpy_ctor> > >
min_element (FwdIter<lt_comp<base<cpy_ctor> > >,
FwdIter<lt_comp<base<cpy_ctor> > >,
binary_predicate<lt_comp<base<cpy_ctor> > >);
template
FwdIter<lt_comp<base<cpy_ctor> > >
max_element (FwdIter<lt_comp<base<cpy_ctor> > >,
FwdIter<lt_comp<base<cpy_ctor> > >);
template
FwdIter<lt_comp<base<cpy_ctor> > >
max_element (FwdIter<lt_comp<base<cpy_ctor> > >,
FwdIter<lt_comp<base<cpy_ctor> > >,
binary_predicate<lt_comp<base<cpy_ctor> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
// exercises min, max: 25.3.7
template <class T, class Predicate>
void test_min_max (int line,
const char a,
const char b,
const T*,
const Predicate *ppred,
bool test_min)
{
const char* const tname = "UserClass";
const char* const fname = test_min ? "min" : "max";
const char* const funname = Predicate::name();
T ta, tb;
ta.data_.val_ = a;
tb.data_.val_ = b;
const int exp_id =
test_min ? b < a ? tb.id_ : ta.id_ : b > a ? tb.id_ : ta.id_;
const char exp_res = test_min ? b < a ? b : a : b > a ? b : a;
const Predicate pred (0, 0); // dummy arguments
const T& res = ppred ?
test_min ? std::min (ta, tb, pred) : std::max (ta, tb, pred)
: test_min ? std::min (ta, tb) : std::max (ta, tb);
// verify 25.3.7 p2, p3, p5, p6
rw_assert (exp_res == res.data_.val_ && exp_id == res.origin_, 0, line,
"line %d %s <%s%{?}, %s%{;}> (%#c, %#c) returned "
"value %#c, id %d; expected value %#c, id %d",
__LINE__, fname, tname, 0 != ppred, funname, a, b,
res.data_.val_, res.origin_, exp_res, exp_id);
}
/**************************************************************************/
// exrcises min_element, max_element: 25.3.7
template <class T, class ForwardIterator, class Predicate>
void test_min_max_element (int line,
const char *src,
const std::size_t min_off,
const std::size_t max_off,
const ForwardIterator &it,
const T*,
const Predicate *ppred,
bool test_min)
{
const char* const itname = type_name (it, (T*)0);
const char* const fname = test_min ? "min_element" : "max_element";
const char* const funname = Predicate::name();
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xsrc_end = xsrc + nsrc;
const ForwardIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const ForwardIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
Predicate pred (0, 0);
const std::size_t last_n_op_lt = T::n_total_op_lt_;
ForwardIterator res (0, 0, 0);
if (ppred) {
res = test_min ?
std::min_element (first, last, pred)
: std::max_element (first, last, pred);
}
else {
res = test_min ?
std::min_element (first, last)
: std::max_element (first, last);
}
// verify the returned value: 25.3.7 p7, p9
const std::size_t off = test_min ? min_off : max_off;
rw_assert (res.cur_ == xsrc + off, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (\"%s\", %zu, ...) "
"got first + %td, expected first + %zu",
__LINE__, fname, itname, 0 != ppred, funname, src, off,
res.cur_ - xsrc, off);
const std::size_t n_ops_lt = ppred ?
Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
// verify the complexity: 25.3.7 p8, p10
std::size_t n_exp_ops = nsrc > 0 ? nsrc - 1 : 0;
rw_assert (n_ops_lt == n_exp_ops, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (\"%s\", %zu, ...) "
"complexity: got %zu, expected %zu",
__LINE__, fname, itname, 0 != ppred, funname, src, off,
n_ops_lt, n_exp_ops);
delete[] xsrc;
}
/**************************************************************************/
template <class T, class Predicate>
void test_min_max (const T*,
const Predicate *ppred,
bool test_min)
{
const char* const tname = "UserClass";
const char* const fname = test_min ? "min" : "max";
const char* const funname = Predicate::name();
rw_info (0, 0, 0,
"const %s& std::%s(const %1$s&, const %1$s&%{?}, %s%{;})",
tname, fname, 0 != ppred, funname);
#define TEST(a, b) \
test_min_max (__LINE__, a, b, (T*)0, ppred, test_min)
TEST ('a', 'a');
TEST ('a', 'b');
TEST ('b', 'a');
TEST ('b', 'b');
TEST ('a', 'e');
TEST ('e', 'a');
#undef TEST
}
/**************************************************************************/
template <class T, class ForwardIterator, class Predicate>
void test_min_max_element (const ForwardIterator &it,
const T*,
const Predicate *ppred,
bool test_min)
{
const char* const itname = type_name (it, (T*)0);
const char* const fname = test_min ? "min_element" : "max_element";
const char* const funname = Predicate::name();
rw_info (0, 0, 0,
"%s std::%s(%1$s, %1$s%{?}, %s%{;})",
itname, fname, 0 != ppred, funname);
#define TEST(src, min_off, max_off) \
test_min_max_element (__LINE__, src, min_off, max_off, it, \
(T*)0, ppred, test_min)
TEST ("", 0, 0);
TEST ("a", 0, 0);
TEST ("ab", 0, 1);
TEST ("aa", 0, 0);
TEST ("ba", 1, 0);
TEST ("abcdefghij", 0, 9);
TEST ("bacdefghji", 1, 8);
TEST ("bcadefgjhi", 2, 7);
TEST ("bcdaefjghi", 3, 6);
TEST ("bcdeajfghi", 4, 5);
TEST ("bcdejafghi", 5, 4);
TEST ("bcdjefaghi", 6, 3);
TEST ("bcjdefgahi", 7, 2);
TEST ("bjcdefghai", 8, 1);
TEST ("jbcdefghia", 9, 0);
TEST ("jihgfedcba", 9, 0);
TEST ("aaaaaaaaaa", 0, 0);
TEST ("ababababab", 0, 1);
TEST ("bababababa", 1, 0);
TEST ("aaaaabaaaa", 0, 5);
TEST ("bbbbbabbbb", 5, 0);
#undef TEST
}
/**************************************************************************/
/* extern */ int rw_opt_no_min; // --no-min
/* extern */ int rw_opt_no_max; // --no-max
/* extern */ int rw_opt_no_min_element; // --no-min_element
/* extern */ int rw_opt_no_max_element; // --no-max_element
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T, class Predicate>
void test_min_max_element (const T*,
const Predicate *ppred,
bool test_min)
{
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}> "
"%1$s std::%s (%1$s, %1$s%{?}, %s%{;})",
"ForwardIterator", ppred, "Compare",
test_min ? "min_element" : "max_element", ppred, "Compare");
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, __LINE__, "ForwardIterator test disabled");
}
else {
test_min_max_element (fwd_iter, (T*)0, ppred, test_min);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_min_max_element (bidir_iter, (T*)0, ppred, test_min);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, 0, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_min_max_element (rand_iter, (T*)0, ppred, test_min);
}
}
/**************************************************************************/
template <class T, class Predicate>
void test_alg_min_max (const T*,
const Predicate *ppred)
{
if (rw_opt_no_min) {
rw_note (0, 0, __LINE__, "std::min test disabled");
}
else {
test_min_max ((T*)0, ppred, true);
}
if (rw_opt_no_max) {
rw_note (0, 0, __LINE__, "std::max test disabled");
}
else {
test_min_max ((T*)0, ppred, false);
}
if (rw_opt_no_min_element) {
rw_note (0, 0, __LINE__, "std::min_element test disabled");
}
else {
test_min_max_element ((T*)0, ppred, true);
}
if (rw_opt_no_max_element) {
rw_note (0, 0, __LINE__, "std::max_element test disabled");
}
else {
test_min_max_element ((T*)0, ppred, false);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_alg_min_max ((UserClass*)0, (Less<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, 0, __LINE__, "std.alg.min.max predicate tests disabled");
}
else {
test_alg_min_max ((UserClass*)0, (Less<UserClass>*)1);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.min.max",
0 /* no comment */, run_test,
"|-no-min#"
"|-no-max#"
"|-no-min_element#"
"|-no-max_element#"
"|-no-predicate#"
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator",
&rw_opt_no_min,
&rw_opt_no_max,
&rw_opt_no_min_element,
&rw_opt_no_max_element,
&rw_opt_no_predicate,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,291 @@
/***************************************************************************
*
* 25.mismatch.cpp - test exercising 25.1.7 [lib.mismatch]
*
* $Id: 25.mismatch.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for mismatch
#include <functional> // for equal_to
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()...
/**************************************************************************/
// exercises std::mismatch()
template <class InputIterator1, class InputIterator2, class T>
void test_mismatch (std::size_t N,
const InputIterator1 &it1_dummy,
const InputIterator2 &it2_dummy,
T*,
const char *predicate)
{
static const char* const it1name = type_name (it1_dummy, (T*)0);
static const char* const it2name = type_name (it2_dummy, (T*)0);
rw_info (0, 0, 0, "std::mismatch (%s, %1$s, %s%{?}, %s%{;})",
it1name, it2name, 0 != predicate, predicate);
// generate sequential values for each default constructed UserClass
// for both lists
UserClass::gen_ = gen_seq_2lists;
// use ::operator new() to prevent default initialization
const std::size_t size = N * sizeof (UserClass);
UserClass *buf1 = _RWSTD_STATIC_CAST (UserClass*, ::operator new (size));
UserClass *buf2 = _RWSTD_STATIC_CAST (UserClass*, ::operator new (size));
const std::size_t mid_inx = N / 2;
for (std::size_t i = 0; i != N; ++i) {
// default-construct a new UserClass at the end of the array
new (buf1 + i) UserClass ();
// build a nearly identical list only missing N/2 (the N/2th
// element) from it's list
if (i != mid_inx)
new (buf2 + i) UserClass ();
}
new (buf2 + mid_inx) UserClass ();
for (std::size_t i = 0; i != N; ++i) {
// exercise 25.1.7 - std::mismatch<>()
std::size_t last_n_op_eq = UserClass::n_total_op_eq_;
UserClass* const buf1_end = buf1 + i + 1;
UserClass* const buf2_end = buf2 + i + 1;
const InputIterator1 first1 (buf1, buf1, buf1_end);
const InputIterator1 last1 (buf1_end, buf1_end, buf1_end);
const InputIterator2 first2 (buf2, buf2, buf2_end);
const std::equal_to<UserClass> pred = std::equal_to<UserClass>();
const std::pair<InputIterator1, InputIterator2> result =
predicate ? std::mismatch (first1, last1, first2, pred)
: std::mismatch (first1, last1, first2);
// verify 25.1.7, p2
UserClass* const expected_buf1_end =
(i < mid_inx) ? buf1_end : buf1 + mid_inx;
UserClass* const expected_buf2_end =
(i < mid_inx) ? buf2_end : buf2 + mid_inx;
UserClass* const res_buf1_end =
buf1 + (result.first.cur_ - first1.cur_);
UserClass* const res_buf2_end =
buf2 + (result.second.cur_ - first2.cur_);
// check that the returned iterators are valid
bool success =
buf1 <= res_buf1_end && res_buf1_end <= buf1_end &&
buf2 <= res_buf2_end && res_buf2_end <= buf2_end;
rw_assert (success, 0, __LINE__,
"%zu. mismatch (%s, %2$s, %s%{?}, %s%{;}): "
"result { %d, %d } out of range: expected "
"{ [0, %d], [0, %d] }",
i, it1name, it2name, 0 != predicate, predicate,
res_buf1_end - buf1, res_buf2_end - buf2,
buf1_end - buf1, buf2_end - buf2);
// iterators are valid check that the algorithm works correctly
success =
res_buf1_end->data_.val_ == expected_buf1_end->data_.val_
&& res_buf2_end->data_.val_ == expected_buf2_end->data_.val_;
rw_assert (success, 0, __LINE__,
"%zu. mismatch (%s, %2$s, %s%{?}, %s%{;}): "
"correctness: got: %d "
"expected: %d, got: %d expected: %d",
i, it1name, it2name, 0 != predicate, predicate,
res_buf1_end->data_.val_, expected_buf1_end->data_.val_,
res_buf2_end->data_.val_, expected_buf2_end->data_.val_);
// verify 25.1.7, p3
success = UserClass::n_total_op_eq_ - last_n_op_eq <= (N + 1);
rw_assert (success, 0, __LINE__,
"%zu. mismatch (%s, %2$s, %s%{?}, %s%{;}): "
"complexity: %zu <= %zu",
i, it1name, it2name, 0 != predicate, predicate,
UserClass::n_total_op_eq_, i + 1);
if (!success)
break;
}
::operator delete (buf1);
::operator delete (buf2);
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 32; // --nloops
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
template <class InputIterator, class T>
void test_mismatch (const InputIterator &dummy, T*, const char *predicate)
{
// check that the number of loops is non-negative
rw_fatal (-1 < rw_opt_nloops, 0, 0,
"number of loops must be non-negative, got %d",
rw_opt_nloops);
const std::size_t N = std::size_t (rw_opt_nloops);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_mismatch (N, dummy, InputIter<UserClass>(0, 0, 0),
(UserClass*)0, predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_mismatch (N, dummy, FwdIter<UserClass>(),
(UserClass*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_mismatch (N, dummy, BidirIter<UserClass>(),
(UserClass*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_mismatch (N, dummy, RandomAccessIter<UserClass>(),
(UserClass*)0, predicate);
}
}
/**************************************************************************/
static void
test_mismatch (const char *predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s> "
"std::pair<%1$s, %2$s> "
"std::mismatch (%1$s, %1$s, %2$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2",
0 != predicate, predicate);
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_mismatch (InputIter<UserClass>(0, 0, 0), (UserClass*)0, predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_mismatch (ConstFwdIter<UserClass>(), (UserClass*)0, predicate);
test_mismatch (FwdIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_mismatch (ConstBidirIter<UserClass>(), (UserClass*)0, predicate);
test_mismatch (BidirIter<UserClass>(), (UserClass*)0, predicate);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_mismatch (ConstRandomAccessIter<UserClass>(),
(UserClass*)0, predicate);
test_mismatch (RandomAccessIter<UserClass>(), (UserClass*)0, predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_mismatch (0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "Predicate test disabled");
}
else {
test_mismatch ("std::equal_to<UserClass>");
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.mismatch",
0 /* no comment */, run_test,
"|-nloops#"
"|-no-InputIterator#"
"|-no-ForwardIterator#"
"|-no-BidirectionalIterator#"
"|-no-RandomAccessIterator#"
"|-no-Predicate",
&rw_opt_nloops,
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,313 @@
/***************************************************************************
*
* 25.nth.element.cpp - test exercising 25.3.2 [lib.alg.nth.element]
*
* $Id: 25.nth.element.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for nth_element,
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
nth_element (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
nth_element (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct StrictWeakLess
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
StrictWeakLess (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "StrictWeakLess"; }
private:
void operator= (StrictWeakLess&); // not assignable
};
template<class T>
std::size_t StrictWeakLess<T>::funcalls_;
/**************************************************************************/
// exrcises nth_element
template <class T, class Predicate>
void test_nth_element (int line,
const char *src,
const std::size_t N,
const std::size_t nth,
const T*,
const Predicate *ppred)
{
_RWSTD_UNUSED (ppred);
typedef RandomAccessIter<T> RandIter;
const RandIter it(0, 0, 0);
const char* const itname = type_name (it, (T*)0);
const char* const fname = "nth_element";
const char* const funname = Predicate::name();
const std::size_t nsrc = src ? std::strlen (src) : N;
T::gen_ = gen_rnd;
T* const xsrc = src ? T::from_char (src, nsrc) : new T[nsrc];
T* const xsrc_end = xsrc + nsrc;
// current, first, last
const RandIter first = make_iter (xsrc, xsrc, xsrc_end, it);
const RandIter nth_it = make_iter (xsrc + nth, xsrc, xsrc_end, it);
const RandIter last = make_iter (xsrc_end, xsrc, xsrc_end, it);
Predicate pred (0, 0);
const std::size_t last_n_op_lt = T::n_total_op_lt_;
if (ppred)
std::nth_element (first, nth_it, last, pred);
else
std::nth_element (first, nth_it, last);
// check the results, 25.3.2, p1
bool success = true;
std::size_t i = 0;
std::size_t j = 0;
for (i = 0; i < nth; i++) {
for (j = nth; j < nsrc; j++) {
success = xsrc[i].data_.val_ <= xsrc[j].data_.val_;
if (!success)
break;
}
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < nth ? i : nth - 1;
j = j < nsrc ? j : nsrc - 1;
if (src) {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}>(\"%s\", %zu, ...) ==> "
"\"%{X=*.*}\", got %#c at %zu !< %#c at %zu",
__LINE__, fname, itname, ppred, funname, src, nth,
int (nsrc), -1, xsrc, xsrc[i].data_.val_, i,
xsrc[j].data_.val_, j);
}
else {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}>(%zu, %zu, ...) "
"got %d at %zu !< %d at %zu",
__LINE__, fname, itname, ppred, funname, N, nth,
xsrc[i].data_.val_, i, xsrc[j].data_.val_, j);
}
// check the complexity, 25.3.2, p2
// it should be linear, i.e. <= K * N, there K << N
// after tests on random sequences use K == 8 as upper bound
std::size_t n_ops =
ppred ? Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
std::size_t exp_ops = 8 * nsrc;
success = n_ops <= exp_ops;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}>(%{?}\"%s\"%{;}%{?}%zu%{;}, "
"%zu, ...): complexity: got %zu, expected no more than %zu",
__LINE__, fname, itname, ppred, funname,
src, src, !src, N, nth, n_ops, exp_ops);
delete[] xsrc;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 256; // --nloops=#
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_complexity; // --no-complexity
/**************************************************************************/
template <class T, class Predicate>
void test_nth_element (const T*,
const Predicate *ppred)
{
typedef RandomAccessIter<T> RandIter;
const char* const itname = type_name (RandIter (0, 0, 0), (T*)0);
const char* const fname = "nth_element";
const char* const funname = Predicate::name();
rw_info (0, 0, 0,
"std::%s (%s, %2$s, %2$s%{?}, %s%{;})",
fname, itname, ppred, funname);
#define TEST(src, nth) \
test_nth_element (__LINE__, src, 0, nth, (T*)0, ppred)
TEST ("a", 0);
TEST ("aa", 1);
TEST ("ab", 0);
TEST ("jihgfedcba", 0);
TEST ("jihgfedcba", 1);
TEST ("jihgfedcba", 2);
TEST ("jihgfedcba", 3);
TEST ("jihgfedcba", 4);
TEST ("jihgfedcba", 5);
TEST ("jihgfedcba", 6);
TEST ("jihgfedcba", 7);
TEST ("jihgfedcba", 8);
TEST ("jihgfedcba", 9);
TEST ("abcdefghij", 0);
TEST ("abcdefghij", 1);
TEST ("abcdefghij", 2);
TEST ("abcdefghij", 3);
TEST ("abcdefghij", 4);
TEST ("abcdefghij", 5);
TEST ("abcdefghij", 6);
TEST ("abcdefghij", 7);
TEST ("abcdefghij", 8);
TEST ("abcdefghij", 9);
TEST ("jijgfgdcda", 5);
TEST ("jihifefcbc", 5);
TEST ("jiigffdcca", 5);
TEST ("jihhfeecbb", 5);
TEST ("cbbbbbbbba", 5);
TEST ("ccbbbbbbaa", 5);
TEST ("abadedghgj", 5);
TEST ("abcbefehih", 5);
TEST ("abbdeeghhj", 5);
TEST ("abcceffhii", 5);
TEST ("abbbbbbbbc", 5);
TEST ("aabbbbbbcc", 5);
#undef TEST
if (rw_opt_no_complexity) {
rw_note (0, 0, 0,
"std::%s (%s, %2$s, %2$s%{?}, %s%{;}): "
"complexity test disabled",
fname, itname, ppred, funname);
}
else {
rw_info (0, 0, 0,
"std::%s (%s, %2$s, %2$s%{?}, %s%{;}): complexity test",
fname, itname, ppred, funname);
const std::size_t N = std::size_t (rw_opt_nloops);
for (std::size_t i = 1; i < N; i++)
test_nth_element (__LINE__, 0, i, i / 2, (T*)0, ppred);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
rw_info (0, 0, 0,
"template <class %s> "
"void std::nth_element (%1$s, %1$s, %1$s)",
"RandomAccessIterator");
test_nth_element ((UserClass*)0, (StrictWeakLess<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::nth_element predicate test disabled");
}
else {
rw_info (0, 0, 0,
"template <class %s, class %s> "
"void std::nth_element (%1$s, %1$s, %1$s, %2$s)",
"RandomAccessIterator", "StrictWeakLess");
const StrictWeakLess<UserClass> pred(0, 0);
test_nth_element ((UserClass*)0, &pred);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.nth_element",
0 /* no comment */,
run_test,
"|-nloops#0 " // must be non-negative
"|-no-predicate#"
"|-no-complexity",
&rw_opt_nloops,
&rw_opt_no_predicate,
&rw_opt_no_complexity);
}

View File

@@ -0,0 +1,487 @@
/***************************************************************************
*
* 25.partial.sort.cpp - test exercising [lib.partial.sort]
*
* $Id: 25.partial.sort.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for partial_sort, partial_sort_copy
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
partial_sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
partial_sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
template
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >
partial_sort_copy (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >
partial_sort_copy (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
template <class Iterator, class CopyIterator, class T, class Predicate>
void test_partial_sort (int line,
const char *src,
const std::size_t N,
const std::size_t mid,
const Iterator &it,
const CopyIterator &itc,
const T* ,
const Predicate *ppred,
bool copy)
{
typedef RandomAccessIter<T> RandIter;
const RandIter rand_it(0, 0, 0);
const char* const itname =
copy ? type_name (itc, (T*)0) : type_name (it, (T*)0);
const char* const outname = "RandomAccessIterator";
const char* const fname = copy ? "partial_sort_copy" : "partial_sort";
const char* const funname = ppred ? Predicate::name() : "operator<()";
// generate random values for each default constructed T
T::gen_ = gen_rnd;
const std::size_t nsrc = src ? std::strlen (src) : N;
T* const xsrc = src ? T::from_char (src, nsrc) : new T[nsrc];
T* const xdst = new T [mid];
T* res_x = copy ? xdst : xsrc;
T* const xsrc_end = xsrc + nsrc;
T* const xdst_end = xdst + mid;
const Iterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const Iterator middle = make_iter (xsrc + mid, xsrc, xsrc_end, it);
const Iterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
CopyIterator first_c = make_iter (xsrc, xsrc, xsrc_end, itc);
CopyIterator last_c = make_iter (xsrc_end, xsrc, xsrc_end, itc);
RandIter res_first = make_iter (xdst, xdst, xdst_end, rand_it);
RandIter res_last = make_iter (xdst_end, xdst, xdst_end, rand_it);
const Predicate pred (0, 0);
RandIter result (0, 0, 0);
std::size_t last_n_op_lt = T::n_total_op_lt_;
if (copy) {
if (ppred)
result = std::partial_sort_copy (
first_c, last_c, res_first, res_last, pred);
else
result = std::partial_sort_copy (
first_c, last_c, res_first, res_last);
}
else {
if (ppred)
std::partial_sort (first, middle, last, pred);
else
std::partial_sort (first, middle, last);
}
bool success = true;
// check the returned iterator for copy version
if (copy) {
success = result.cur_ == res_first.cur_ + mid;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> (): "
"returned iterator it is invalid: got result + %td, "
"expected result + %zu",
__LINE__, fname, itname, copy, outname, ppred, funname,
result.cur_ - res_first.cur_, mid);
}
// check that the array is sorted
success = is_sorted_lt (res_x, res_x + mid);
if (src) {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
"(\"%s\", %zu, ...): ==> \"%{X=*.*}\" not sorted",
__LINE__, fname, itname, copy, outname, ppred, funname,
src, mid, int (mid), -1, res_x);
}
else {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
"(%zu, %zu, ...): not sorted",
__LINE__, fname, itname, copy, outname, ppred, funname,
nsrc, mid);
}
// check that any element in the sorted range <= that any element
// in the rest part of the array
int max_el = res_x[0].data_.val_;
std::size_t j = 1;
for ( ; j < mid; j++)
max_el = max_el < res_x[j].data_.val_ ? res_x[j].data_.val_ : max_el;
if (copy) {
std::size_t tmp = 0;
for (j = 0; j < nsrc; j++)
if (max_el > xsrc[j].data_.val_)
tmp++;
success = tmp <= mid;
}
else {
for (j = mid; j < nsrc; j++) {
success = max_el <= xsrc[j].data_.val_;
if (! success)
break;
}
}
// to avoid error in trace mode
j = j < nsrc ? j : nsrc - 1;
if (src) {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
"(\"%s\", %zu, ...): ==> \"%{X=*.*}\" got less element "
"%{?}%#c%{;} in the unsorted part",
__LINE__, fname, itname, copy, outname, ppred, funname,
src, mid, int (copy ? mid : nsrc), -1, res_x,
!copy, xsrc[j].data_.val_);
}
else {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
"(%zu, %zu, ...): got less element in the unsorted part",
__LINE__, fname, itname, copy, outname, ppred, funname,
nsrc, mid);
}
// verify 25.3.1.1, p2 and 25.3.1.2, p3
// the complexity of our implementation is no worse than
// 3.33 * N * log (N) (hence the magic 7 and 2)
std::size_t n_ops =
ppred ? Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
std::size_t exp_ops = 7 * nsrc * ::ilog2 (mid > 1 ? mid : 2);
success = 2 * n_ops <= exp_ops;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> (): complexity "
"for length %zu is %zu, expected no more than %zu",
__LINE__, fname, itname, copy, outname, ppred, funname,
nsrc, n_ops, exp_ops / 2);
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 256; // --nloops=#
/* extern */ int rw_opt_no_partial_sort; // --no-partial_sort
/* extern */ int rw_opt_no_partial_sort_copy; // --no-partial_sort_copy
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_complexity; // --no-complexity
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class Iterator, class CopyIterator, class T, class Predicate>
void test_partial_sort (const std::size_t N,
const Iterator &it,
const CopyIterator &itc,
const T* ,
const Predicate *ppred,
bool copy)
{
const char* const itname =
copy ? type_name (itc, (T*)0) : type_name (it, (T*)0);
const char* const outname = "RandomAccessIterator";
const char* const fname = copy ? "partial_sort_copy" : "partial_sort";
const char* const funname = ppred ? Predicate::name() : "operator<()";
rw_info (0, 0, 0,
"%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})",
copy, outname, fname, itname, copy ? outname : itname,
copy, ppred, funname);
#define TEST(src, mid) \
test_partial_sort (__LINE__, src, 0, mid, it, itc, (T*)0, ppred, copy)
TEST ("a", 1);
TEST ("ba", 1);
TEST ("cba", 1);
TEST ("dcba", 2);
TEST ("edcba", 2);
TEST ("fedcba", 3);
TEST ("gfedcba", 3);
TEST ("hgfedcba", 4);
TEST ("ihgfedcba", 4);
TEST ("jihgfedcba", 5);
TEST ("ab", 1);
TEST ("abc", 1);
TEST ("abcd", 2);
TEST ("abcde", 2);
TEST ("abcdef", 3);
TEST ("abcdefg", 3);
TEST ("abcdefgh", 4);
TEST ("abcdefghi", 4);
TEST ("abcdefghij", 5);
TEST ("aa", 1);
TEST ("aabb", 2);
TEST ("bbccaa", 3);
TEST ("ddbbccaa", 4);
TEST ("ddeebbccaa", 5);
TEST ("aa", 2);
TEST ("aabb", 4);
TEST ("bbccaa", 6);
TEST ("ddbbccaa", 8);
TEST ("ddeebbccaa", 10);
TEST ("aaaaaaaaaa", 5);
TEST ("ababababab", 4);
TEST ("bababababa", 4);
#undef TEST
if (rw_opt_no_complexity) {
rw_note (0, 0, 0,
"%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})"
": complexity test disabled",
copy, outname, fname, itname, copy ? outname : itname,
copy, ppred, funname);
}
else {
rw_info (0, 0, 0,
"%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})"
": complexity test",
copy, outname, fname, itname, copy ? outname : itname,
copy, ppred, funname);
for (std::size_t i = 1; i < N; i++)
test_partial_sort (__LINE__, 0, i, i > 1 ? i / 2 : 1, it, itc,
(T*)0, ppred, copy);
}
}
/**************************************************************************/
template <class T, class Predicate>
void test_partial_sort (const std::size_t N,
const T* ,
const Predicate *ppred,
bool copy)
{
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}%{?}, class %s%{;}> "
"%s std::partial_sort%{?}_copy%{;} (%1$s%{?}, %1$s%{;}, %1$s"
"%{?}, %3$s, %3$s%{;}%{?}, %5$s%{;})",
copy ? "InputIterator" : "RandomAccessIterator",
copy, "RandomAccessIterator", ppred, "StrictWeakComp",
copy ? "RandomAccessIterator" : "void",
copy, !copy, copy, ppred);
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
if (! copy) {
test_partial_sort (N, rand_iter, rand_iter,
(T*)0, ppred, false);
return;
}
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_partial_sort (N, rand_iter, input_iter,
(T*)0, ppred, true);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_partial_sort (N, rand_iter, fwd_iter,
(T*)0, ppred, true);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_partial_sort (N, rand_iter, bidir_iter,
(T*)0, ppred, true);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_partial_sort (N, rand_iter, rand_iter,
(T*)0, ppred, true);
}
}
/**************************************************************************/
template <class T>
void test_partial_sort (const std::size_t N,
const T* ,
bool copy)
{
test_partial_sort (N, (T*)0, (Less<T>*)0, copy);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::partial_sort%{?}_copy%{;} predicate test disabled",
copy);
}
else {
const Less<T> pred(0, 0);
test_partial_sort (N, (T*)0, &pred, copy);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
const std::size_t N = std::size_t (rw_opt_nloops);
if (rw_opt_no_partial_sort) {
rw_note (0, __FILE__, __LINE__,
"std::partial_sort test disabled");
}
else {
test_partial_sort (N, (UserClass*)0, false);
}
if (rw_opt_no_partial_sort_copy) {
rw_note (0, __FILE__, __LINE__,
"std::partial_sort_copy test disabled");
}
else {
test_partial_sort (N, (UserClass*)0, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.partial.sort",
0 /* no comment */,
run_test,
"|-nloops#0 " // must be non-negative
"|-no-partial_sort# "
"|-no-partial_sort_copy# "
"|-no-InputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator# "
"|-no-predicate",
&rw_opt_nloops,
&rw_opt_no_partial_sort,
&rw_opt_no_partial_sort_copy,
&rw_opt_no_input_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate,
&rw_opt_no_complexity);
}

View File

@@ -0,0 +1,350 @@
/***************************************************************************
*
* 25.partitions.cpp - test exercising 25.2.12 [lib.alg.partitions]
*
* $Id: 25.partitions.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for partition, stable_partition
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
BidirIter<assign<base<cpy_ctor> > >
partition (BidirIter<assign<base<cpy_ctor> > >,
BidirIter<assign<base<cpy_ctor> > >,
predicate<assign<base<cpy_ctor> > >);
template
BidirIter<assign<base<cpy_ctor> > >
stable_partition (BidirIter<assign<base<cpy_ctor> > >,
BidirIter<assign<base<cpy_ctor> > >,
predicate<assign<base<cpy_ctor> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct GreaterThanPredicate
{
static std::size_t funcalls_;
// dummy argument provide to prevent implicit conversions
GreaterThanPredicate (int value, int /* dummy */)
: value_(value) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &arg) {
++funcalls_;
return conv_to_bool::make (value_ < arg.data_.val_);
}
static const char* name () { return "GreaterThanPredicate"; }
private:
const int value_;
void operator= (GreaterThanPredicate&); // not assignable
};
template<class T> std::size_t GreaterThanPredicate<T>::funcalls_;
/**************************************************************************/
// exercises std::partition() and std::stable_partition()
template <class T, class Iterator, class Predicate>
void test_partitions (int line,
const char *src,
const char *dst,
const int value,
const std::size_t offset,
const Iterator &it,
const Predicate *,
const T*,
bool stable)
{
const char* const itname = type_name (it, (T*)0);
const char* const fname = stable ? "stable_partition" : "partition";
const char* const funname = Predicate::name();
const std::size_t nsrc = std::strlen (src);
const std::size_t ndst = std::strlen (dst);
T* const xsrc = T::from_char (src, nsrc);
T* const xdst = T::from_char (dst, ndst);
T* const xsrc_end = xsrc + nsrc;
const Iterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const Iterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
const std::size_t last_n_op_assign = T::n_total_op_assign_;
const std::size_t t_n_ctors = T::n_total_def_ctor_ + T::n_total_copy_ctor_;
const std::size_t t_n_dtors = T::n_total_dtor_;
const Predicate pred (value, 0 /* dummy */);
const Iterator res =
stable ? std::stable_partition (first, last, pred)
: std::partition (first, last, pred);
// check that there is no leaked objects
const std::size_t t_n_objs_diff =
T::n_total_def_ctor_ + T::n_total_copy_ctor_
- t_n_ctors - T::n_total_dtor_ + t_n_dtors;
bool success = 0 == t_n_objs_diff;
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
"number of objects changed on %d: %s detected",
__LINE__, fname, itname, funname, src,
int (nsrc), -1, xsrc, t_n_objs_diff,
t_n_objs_diff > 0 ? "memory leak" : "unexpected dtor call");
// check that the returned iterator points to the expected element
success = res.cur_ == first.cur_ + offset;
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
"returned iterator it = first + %td, expected first + %zu",
__LINE__, fname, itname, funname, src, int (nsrc),
-1, xsrc, res.cur_ - first.cur_, offset);
// check 25.2.12, p2 & p5
// "left" part of the array there the predicate should be true
std::size_t i = 0;
for ( ; i < offset; i++) {
success = xsrc[i].data_.val_ > value;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...) "
"==> \"%{X=*.*}\", at %zu got: %#c !> %#c",
__LINE__, fname, itname, funname, src, int (nsrc),
-1, xsrc, i + 1, xsrc[i].data_.val_, value);
// "right" part of the array there the predicate should be false
for ( ; i < nsrc; i++) {
success = xsrc[i].data_.val_ <= value;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...) "
"==> \"%{X=*.*}\", at %zu got: %#c !<= %#c",
__LINE__, fname, itname, funname, src, int (nsrc),
-1, xsrc, i + 1, xsrc[i].data_.val_, value);
// check the complexity, 25.2.12 p3 & p6
// first check number of swaps, 2 assignments per swap
// add 1 in case of stable_partition to avoid the assertion failing
// when i == 0 (only one element presents in the sequence)
// is this one extra assignment an algorithm bug??
// the standard talks about swaps only, not about assignments
// and there are 0 swaps (1 swap equals 2 assignments) in this case...
std::size_t exp_assigns = stable ? 2 * nsrc * ::ilog2 (nsrc) + 1 : nsrc;
std::size_t op_assigns = T::n_total_op_assign_ - last_n_op_assign;
success = op_assigns <= exp_assigns;
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...): complexity: "
"got %zu assignments, expected no more than %zu",
__LINE__, fname, itname, funname, src,
op_assigns, exp_assigns);
// second check the number of the predicate calls
success = Predicate::funcalls_ == nsrc;
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...): complexity: "
"got %zu applications of the predicate, "
"expected no more than %zu",
__LINE__, fname, itname, funname, src,
Predicate::funcalls_, nsrc);
if (stable) {
// check the stable_partition is really stable 25.2.12, p5
for (i = 0; i < nsrc; i++) {
success = xsrc[i].data_.val_ == xdst[i].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
"expected \"%{X=*.*}\", realtive order broken at %zu, "
"%#c != %#c",
__LINE__, fname, itname, funname, src,
int (nsrc), int (i), xsrc, int (ndst), int (i), xdst,
i, xsrc[i].data_.val_, xdst[i].data_.val_);
}
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
template <class T, class Iterator>
void test_partitions (const Iterator &it,
const T* ,
bool stable)
{
const char* const itname = type_name (it, (T*)0);
const char* const fname =
stable ? "stable_partition" : "partition";
const char* const funname = GreaterThanPredicate<T>::name();
rw_info (0, 0, 0,
"%s %s (%1$s, %1$s, %s)",
itname, fname, funname);
#define TEST(src, dest, mid, offet) \
test_partitions (__LINE__, src, dest, mid, offet, it, \
(GreaterThanPredicate<T>*)0, (T*)0, stable)
// stable_partition fails this test
TEST ("abcdefghij", "abcdefghij", 0, 10);
TEST ("abcdefghij", "bcdefghija", 'a', 9);
TEST ("abcdefghij", "cdefghijab", 'b', 8);
TEST ("abcdefghij", "defghijabc", 'c', 7);
TEST ("abcdefghij", "efghijabcd", 'd', 6);
TEST ("abcdefghij", "fghijabcde", 'e', 5);
TEST ("abcdefghij", "ghijabcdef", 'f', 4);
TEST ("abcdefghij", "hijabcdefg", 'g', 3);
TEST ("abcdefghij", "ijabcdefgh", 'h', 2);
TEST ("abcdefghij", "jabcdefghi", 'i', 1);
TEST ("abcdefghij", "abcdefghij", 'j', 0);
// stable_partition fails this test
TEST ("jihgfedcba", "jihgfedcba", 0, 10);
TEST ("jihgfedcba", "jihgfedcba", 'a', 9);
TEST ("jihgfedcba", "jihgfedcba", 'b', 8);
TEST ("jihgfedcba", "jihgfedcba", 'c', 7);
TEST ("jihgfedcba", "jihgfedcba", 'd', 6);
TEST ("jihgfedcba", "jihgfedcba", 'e', 5);
TEST ("jihgfedcba", "jihgfedcba", 'f', 4);
TEST ("jihgfedcba", "jihgfedcba", 'g', 3);
TEST ("jihgfedcba", "jihgfedcba", 'h', 2);
TEST ("jihgfedcba", "jihgfedcba", 'i', 1);
TEST ("jihgfedcba", "jihgfedcba", 'j', 0);
// stable_partition fails this test
TEST ("a", "a", 0, 1);
TEST ("a", "a", 'a', 0);
}
/**************************************************************************/
/* extern */ int rw_opt_no_partition; // --no-partition
/* extern */ int rw_opt_no_stable_partition; // --no-stable_partition
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T>
void test_partitions (const T*, bool stable)
{
rw_info (0, 0, 0,
"template <class %s, class %s> %1$s %s (%1$s, %1$s, %2$s)",
"BidirectionalIterator", "Predicate",
stable ? "stable_partition" : "partition");
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_partitions (BidirIter<T>(), (T*)0, stable);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_partitions (RandomAccessIter<T>(), (T*)0, stable);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
if (rw_opt_no_partition) {
rw_note (0, __FILE__, __LINE__, "std::partition test disabled");
}
else {
test_partitions ((UserClass*)0, false);
}
if (rw_opt_no_stable_partition) {
rw_note (0, __FILE__, __LINE__,
"std::stable_partition test disabled");
}
else {
test_partitions ((UserClass*)0, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.partitions",
0 /* no comment */, run_test,
"|-no-partition# "
"|-no-stable_partition# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator",
&rw_opt_no_partition,
&rw_opt_no_stable_partition,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,338 @@
/***************************************************************************
*
* 25.permutation.cpp - test exercising lib.alg.permutation.generators
*
* $Id: 25.permutation.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for prev_permutation, next_permutation
#include <cstring> // for strlen, size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
bool
prev_permutation (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >);
template
bool
prev_permutation (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
template
bool
next_permutation (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >);
template
bool
next_permutation (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
// exercise prev_permutation and next_permutation 25.3.9
template <class T, class BidirectIterator, class Predicate>
void test_permutations (int line,
const char *src,
const char *dst,
bool res,
const BidirectIterator &it,
const T*,
const Predicate *ppred,
bool prev)
{
const char* const itname = type_name (it, (T*)0);
const char* const algname = prev ? "prev_permutation" : "next_permutation";
const char* const predname = Predicate::name ();
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xsrc_end = xsrc + nsrc;
const BidirectIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const BidirectIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
const Predicate pred (0, 0);
const std::size_t last_n_op_assign = T::n_total_op_assign_;
bool result = false;
if (ppred) {
result = prev ?
std::prev_permutation (first, last, pred)
: std::next_permutation (first, last, pred);
}
else {
result = prev ?
std::prev_permutation (first, last)
: std::next_permutation (first, last);
}
std::size_t n_ops_assign = T::n_total_op_assign_ - last_n_op_assign;
// verify the returned value: 25.3.9, p1 and p4
bool success = result == res;
rw_assert (success, 0, line,
"line %d. %s <%s%{?}, %s%{;}> (\"%s\", ...) == %b, got %b",
__LINE__, algname, itname, 0 != ppred, predname,
src, result, res);
// verify the permutation result
std::size_t i = 0;
for ( ; i < nsrc; i++) {
success = xsrc [i].data_.val_ == dst [i];
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < nsrc ? i : nsrc - 1;
rw_assert (success, 0, line,
"line %d. %s <%s%{?}, %s%{;}> (\"%s\", ...) "
"==> got \"%{X=*.*}\", expected \"%s\"",
__LINE__, algname, itname, 0 != ppred, predname, src,
int (nsrc), int (i), xsrc, dst);
// verify the complexity: 25.3.9 p2 and p5.
// (last - first) / 2 swaps, 2 assign per swap
success = n_ops_assign <= nsrc;
rw_assert (success, 0, line,
"line %d. %s <%s%{?}, %s%{;}> (\"%s\", ...) "
"complexity: got %zu assigns, expected no more than %zu",
__LINE__, algname, itname, 0 != ppred, predname, src,
n_ops_assign, nsrc);
delete[] xsrc;
}
/**************************************************************************/
template <class T, class BidirectIterator, class Predicate>
void test_permutations (const BidirectIterator &it,
const T*,
const Predicate *ppred,
bool prev)
{
const char* const itname = type_name (it, (T*)0);
const char* const algname = prev ? "prev_permutation" : "next_permutation";
const char* const predname = Predicate::name();
rw_info (0, 0, 0,
"std::%s(%s, %2$s%{?}, %s%{;})",
algname, itname, 0 != ppred, predname);
#define TEST(src, dst, res) \
test_permutations (__LINE__, src, dst, res, it, (T*)0, ppred, prev)
if (prev) {
// +------------- initial (source) sequence
// | +------- final (destination) sequence
// | | +-- expected return value
// | | |
// V V V
TEST ("a", "a", false);
TEST ("aa", "aa", false);
TEST ("ab", "ba", false);
TEST ("ba", "ab", true);
TEST ("bcaefigjhd", "bcaefigjdh", true);
TEST ("bcaefihdgj", "bcaefigjhd", true);
TEST ("hefdiacjbg", "hefdiacgjb", true);
TEST ("hefdiacjgb", "hefdiacjbg", true);
TEST ("aaaaaaaaaa", "aaaaaaaaaa", false);
TEST ("aaaaabbbbb", "bbbbbaaaaa", false);
TEST ("ababababab", "abababaabb", true);
TEST ("bbbbbaaaaa", "bbbbabaaaa", true);
TEST ("abcdefghij", "jihgfedcba", false);
TEST ("jihgfedcba", "jihgfedcab", true);
}
else {
TEST ("a", "a", false);
TEST ("aa", "aa", false);
TEST ("ab", "ba", true);
TEST ("ba", "ab", false);
TEST ("bcaefigjhd", "bcaefihdgj", true);
TEST ("bcaefigjdh", "bcaefigjhd", true);
TEST ("hefdiacjbg", "hefdiacjgb", true);
TEST ("hefdiacgjb", "hefdiacjbg", true);
TEST ("aaaaaaaaaa", "aaaaaaaaaa", false);
TEST ("aaaaabbbbb", "aaaababbbb", true);
TEST ("ababababab", "ababababba", true);
TEST ("bbbbbaaaaa", "aaaaabbbbb", false);
TEST ("abcdefghij", "abcdefghji", true);
TEST ("jihgfedcba", "abcdefghij", false);
}
}
/**************************************************************************/
/* extern */ int rw_opt_no_prev_permutation; // --no-prev_permutation
/* extern */ int rw_opt_no_next_permutation; // --no-next_permutation
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T, class Predicate>
void test_permutations (const T*,
const Predicate* ppred,
bool prev)
{
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}> "
"bool %s (%1$s, %1$s%{?}, %s%{;})",
"BidirectionalIterator", 0 != ppred, "Compare",
prev ? "prev_permutation" : "next_permutation",
0 != ppred, "Compare");
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_permutations (bidir_iter, (T*)0, ppred, prev);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, 0, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_permutations (rand_iter, (T*)0, ppred, prev);
}
}
/**************************************************************************/
template <class T, class Predicate>
void test_permutations (const T*,
const Predicate* ppred)
{
if (rw_opt_no_prev_permutation) {
rw_note (0, 0, __LINE__, "std::prev_permutation test disabled");
}
else {
test_permutations ((UserClass*)0, ppred, true);
}
if (rw_opt_no_next_permutation) {
rw_note (0, 0, __LINE__, "std::next_permutation test disabled");
}
else {
test_permutations ((UserClass*)0, ppred, false);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_permutations ((UserClass*)0, (Less<UserClass>*)0);
if (rw_opt_no_predicate) {
rw_note (0, 0, __LINE__, "predicate test disabled");
}
else {
test_permutations ((UserClass*)0, (Less<UserClass>*)1);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.permutation.generators",
0 /* no comment */,
run_test,
"|-no-prev_permutation# "
"|-no-next_permutation# "
"|-no-predicate# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_prev_permutation,
&rw_opt_no_next_permutation,
&rw_opt_no_predicate,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,394 @@
/***************************************************************************
*
* 25.random.shuffle.cpp - test exercising 25.2.11 [lib.alg.random.shuffle]
*
* $Id: 25.random.shuffle.cpp 650944 2008-04-23 17:27:06Z sebor $
*
***************************************************************************
*
* 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-2008 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <algorithm> // for random_shuffle
#include <cstring> // for memset(), size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
random_shuffle (RandomAccessIter<assign<base<cpy_ctor> > >,
RandomAccessIter<assign<base<cpy_ctor> > >);
template
void
random_shuffle (RandomAccessIter<assign<base<cpy_ctor> > >,
RandomAccessIter<assign<base<cpy_ctor> > >,
func<const long>&);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// 25.2.11, p3 requires that a RandomNumberGenerator take
// and return a value convertible from and to, respectively,
// iterator::difference_type
template <class DifferenceType>
struct Convertible
{
Convertible (DifferenceType val): val_ (val) { }
operator DifferenceType () /* non-const */ { return val_; }
private:
const DifferenceType val_;
template <class T>
Convertible (T);
};
// detect assumptions made by the algorithm about the return value
// from RandomGenerator::operator() being anything but convertible
// to the iterator's difference type
template <class DifferenceType, class T>
void operator+ (Convertible<DifferenceType>, T);
template <class DifferenceType, class T>
void operator+ (T, Convertible<DifferenceType>);
template <class DifferenceType>
struct RandomGenerator
{
// dummy arguments to prevent the class from being default
// constructible or construtible by conversion from an int
RandomGenerator (int, int) {
ncalls_ = 0;
}
// non-const in order to detect unwarranted assumptions
// in the algorithm(s)
Convertible<DifferenceType>
operator() (DifferenceType n) /* non-const */ {
++ncalls_;
gen_ = (gen_ << 7) + gen_ % 128;
// prevent the number from going negative(!)
if (gen_ < 0)
gen_ = -gen_;
return gen_ % n;
}
static std::size_t ncalls_;
private:
template <class T>
void operator() (T) /* non-const */;
static DifferenceType gen_;
};
template <class DifferenceType>
std::size_t RandomGenerator<DifferenceType>::ncalls_ = 0;
template <class DifferenceType>
DifferenceType RandomGenerator<DifferenceType>::gen_ = 12345;
/**************************************************************************/
int sequence_start;
int sequence_generator ()
{
return sequence_start++;
}
/**************************************************************************/
// exercises 25.2.11 -- std::random_shuffle()
template <class T, class Iterator, class RandomNumberGenerator>
void test_random_shuffle (const std::size_t line,
const std::size_t N,
const Iterator &it,
const RandomNumberGenerator*,
const T*,
bool rnd_gen)
{
const char* const itname = type_name (it, (T*)0);
const char* const fname = "random_shuffle";
const char* const funname = rnd_gen ? "random_generator" : "";
rw_info (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;})",
fname, itname, rnd_gen, funname);
// generate a sequential value for each default-constructed T
// starting with 0 (i.e., T::val_ will be 0 for the first T)
sequence_start = 0;
T::gen_ = sequence_generator;
T *buf = new T [N + 1];
char *missing = new char [N + 1];
for (std::size_t i = 0; i < N; ++i) {
// create a pair of safe iterator to pass to random_shuffle
// in order to test that the function doesn't write past
// the end of the sequence [first, last)
const Iterator first = make_iter (buf, buf, buf + i, it);
const Iterator last = make_iter (buf + i, buf, buf + i, it);
/* non-const */ RandomNumberGenerator rnd (0, 0); // dummy args
// exercise 25.2.11 - std::random_shuffle<>()
std::size_t n_op_assign = T::n_total_op_assign_;
// shuffle buffer elements
if (rnd_gen)
std::random_shuffle (first, last, rnd);
else
std::random_shuffle (first, last);
n_op_assign = T::n_total_op_assign_ - n_op_assign;
// verify 25.2.11, p1
// iterate over elements of the missing array clearing those
// at the index given by T::val_ to true to verify that the
// algorithm didn't drop any elements
std::size_t j;
std::memset (missing, 1, N);
for (j = 0; j != i; ++j) {
const std::size_t inx = std::size_t (buf [j].data_.val_);
if (inx < N)
missing [inx] = 0;
}
// find the first missing element (if any)
const char* const first_missing = (char*)std::memchr (missing, 1, i);
bool success = 0 == first_missing;
rw_assert (success, 0, line,
"%zu. std::%s<%s%{?}, %s%{;}>(): can't find element "
"with value %td: got \"%{X=*.*}\"",
i, fname, itname, rnd_gen, funname,
first_missing - missing,
int (i), -1, buf);
// verify 25.2.11, p2, complexity:
// exactly K = ((last - first) - 1) swaps
// i.e., K * 2 assignments (at 2 assignment per swap
// plus one copy construction)
success = n_op_assign == 2 * (i ? i - 1 : i);
rw_assert (success, 0, line,
"%zu. std::%s<%s%{?}, %s%{;}>(): complexity: "
"expected %zu swaps, got %zu",
i, fname, itname, rnd_gen, funname,
2 * i, n_op_assign);
}
delete[] buf;
delete[] missing;
}
/**************************************************************************/
void test_random_shuffle (const std::size_t line)
{
#ifndef _RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE
rw_info (0, 0, 0,
"verify that the randomly shuffled sequence "
"matches the expected result, this "
"depends on the implementation of the random "
"number generator used by random_shuffle()");
int array[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
std::random_shuffle (array, array + sizeof array / sizeof *array);
const int result[] = {
0xdc, 0x98, 0x6c, 0xcc, 0x1c, 0xb1, 0x2f, 0x13,
0xa4, 0x8b, 0x96, 0x87, 0x95, 0xd8, 0x5e, 0xd5,
0xb6, 0xee, 0xc3, 0x07, 0x68, 0xe4, 0x4e, 0xc0,
0xb7, 0x40, 0x15, 0x55, 0x31, 0x5f, 0xaf, 0xce,
0x01, 0x51, 0x09, 0x4f, 0x0b, 0x80, 0x28, 0x0f,
0xec, 0x43, 0x8a, 0x14, 0x90, 0x9a, 0x7b, 0x3e,
0x81, 0x1e, 0xab, 0xff, 0xed, 0xf6, 0xca, 0x0c,
0x6a, 0x9c, 0x91, 0x60, 0x27, 0xb2, 0x04, 0xd3,
0x72, 0xd7, 0x08, 0x8c, 0x8e, 0x1b, 0x35, 0x49,
0xba, 0x7a, 0xfd, 0x53, 0x22, 0xaa, 0xf5, 0x93,
0xf2, 0x63, 0x05, 0xb4, 0x33, 0x9b, 0xea, 0xc8,
0xc5, 0x39, 0xfc, 0x5d, 0x56, 0x50, 0xe2, 0xf4,
0xc1, 0xa9, 0x76, 0x99, 0xe7, 0xd0, 0xc6, 0x83,
0x11, 0x77, 0x70, 0xa6, 0x46, 0x38, 0x1d, 0x74,
0x6b, 0xdf, 0x30, 0xcf, 0xd1, 0x29, 0x7f, 0x4b,
0xe8, 0x1f, 0xc4, 0xa1, 0x75, 0xae, 0x3f, 0xf1,
0xad, 0x42, 0x2d, 0xfe, 0x62, 0x61, 0x6d, 0x3d,
0xa7, 0x0a, 0x6e, 0xde, 0x16, 0x36, 0xd2, 0xcb,
0x5c, 0xc2, 0x7c, 0xd6, 0x37, 0xa0, 0x20, 0xb5,
0xf3, 0xac, 0x71, 0x64, 0x26, 0x66, 0x88, 0x23,
0x52, 0xdb, 0x2e, 0x10, 0x84, 0x0e, 0x6f, 0x89,
0xb3, 0x86, 0xe5, 0xe6, 0x25, 0x78, 0xd4, 0x2a,
0xa8, 0x5b, 0xc9, 0x44, 0x24, 0x17, 0x1a, 0xf0,
0x69, 0x7e, 0xbf, 0x8d, 0x5a, 0x82, 0x9e, 0xf9,
0xc7, 0xf7, 0x4c, 0x92, 0x9d, 0x34, 0x02, 0x45,
0x59, 0xe1, 0x48, 0x7d, 0xb9, 0x94, 0x41, 0x47,
0x54, 0x00, 0x3c, 0x65, 0xf8, 0xb8, 0xcd, 0x0d,
0xe9, 0x9f, 0x8f, 0x79, 0x3a, 0xda, 0x4a, 0x97,
0xef, 0xa2, 0x21, 0x58, 0x67, 0x32, 0xb0, 0x3b,
0xe0, 0x85, 0x19, 0x12, 0x2c, 0xbc, 0x4d, 0xe3,
0x2b, 0x03, 0xbe, 0xfb, 0xbd, 0x57, 0xeb, 0x06,
0xfa, 0xbb, 0xdd, 0xa5, 0xa3, 0x73, 0x18, 0xd9
};
for (std::size_t i = 0; i != sizeof array / sizeof *array; ++i) {
const bool success = array [i] == result [i];
if (!success) {
rw_assert (0, 0, line,
"randomly shuffled sequence failed to match "
"the expected result (data portability failure) "
"%d != %d at %zu",
array [i], result [i], i + 1);
}
}
#else
rw_note (0, 0, 0,
"_RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE is defined, "
"no random_test available");
#endif // _RWSTD_NO_EXT_PORTABLE_RANDOM_SEQUENCE
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 1024; // --nloops=#
/* extern */ int rw_opt_no_random; // --no-random
/* extern */ int rw_opt_no_random_generator; // --no-random_generator
/* extern */ int rw_opt_no_rand_test; // --no-rand_test
static int run_test (int, char*[])
{
const std::size_t N = std::size_t (rw_opt_nloops);
typedef RandomAccessIter<UserClass>::difference_type DiffT;
typedef RandomGenerator<DiffT> RandGenT;
if (rw_opt_no_random) {
rw_note (0, __FILE__, __LINE__, "std::random test disabled");
}
else {
rw_info (0, 0, 0,
"template <class %s> "
"std::random_shuffle (%1$s, %1$s)",
"RandomAccessIterator");
test_random_shuffle (__LINE__, N, RandomAccessIter<UserClass>(),
(RandGenT*)0, (UserClass*)0, false);
}
if (rw_opt_no_rand_test) {
rw_note (0, __FILE__, __LINE__, "random algorithm test disabled");
}
else {
test_random_shuffle (__LINE__);
}
if (rw_opt_no_random_generator) {
rw_note (0, __FILE__, __LINE__,
"std::random with random_generator test disabled");
}
else {
rw_info (0, 0, 0,
"template <class %s, class %s> "
"std::random_shuffle (%1$s, %1$s, %2$s)",
"RandomAccessIterator", "RandomNumberGenerator");
test_random_shuffle (__LINE__, N, RandomAccessIter<UserClass>(),
(RandGenT*)0, (UserClass*)0, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.random_shuffle",
0 /* no comment */, run_test,
"|-nloops#0 " // must be non-negative
"|-no-random# "
"|-no-random_generator# "
"|-no-rand_test",
&rw_opt_nloops,
&rw_opt_no_random,
&rw_opt_no_random_generator,
&rw_opt_no_rand_test);
}

View File

@@ -0,0 +1,609 @@
/***************************************************************************
*
* 25.remove.cpp - test exercising 25.2.7 [lib.alg.remove]
*
* $Id: 25.remove.cpp 588637 2007-10-26 13:31:06Z 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.
*
**************************************************************************/
#include <algorithm> // for remove(), remove_copy(), ...
#include <cstring> // for strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
FwdIter<eq_comp<assign<base<> > > >
remove (FwdIter<eq_comp<assign<base<> > > >,
FwdIter<eq_comp<assign<base<> > > >,
const eq_comp<assign<base<> > >&);
template
FwdIter<eq_comp<assign<base<> > > >
remove_if (FwdIter<eq_comp<assign<base<> > > >,
FwdIter<eq_comp<assign<base<> > > >,
predicate<eq_comp<assign<base<> > > >);
template
OutputIter<eq_comp<assign<base<> > > >
remove_copy (InputIter<eq_comp<assign<base<> > > >,
InputIter<eq_comp<assign<base<> > > >,
OutputIter<eq_comp<assign<base<> > > >,
const eq_comp<assign<base<> > >&);
template
OutputIter<eq_comp<assign<base<> > > >
remove_copy_if (InputIter<eq_comp<assign<base<> > > >,
InputIter<eq_comp<assign<base<> > > >,
OutputIter<eq_comp<assign<base<> > > >,
predicate<eq_comp<assign<base<> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// names of tested functions
const char* const fnames[] = { "remove", "remove_copy" };
const char* const fnames_if[] = { "remove_if", "remove_copy_if" };
// tags to select remove or remove_copy at compile time
struct RemoveTag {
enum { fname_inx = 0 };
int use_predicate;
};
struct RemoveCopyTag {
enum { fname_inx = 1 };
int use_predicate;
};
// used as a dummy template argument to test functions exercising remove()
// and remove_if() (to differentiate from remove_copy() and remove_copy_if())
struct NoIterator { };
const char* type_name (NoIterator, const UserClass*)
{
return 0;
}
typedef unsigned char UChar;
// predicate used as an argument to remove_if() and remove_copy_if()
template <class T>
struct EqualityPredicate
{
static std::size_t funcalls_;
EqualityPredicate (const T &val, int /* dummy */)
: val_ (val) {
funcalls_ = 0;
}
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
ConvertibleToBool operator() (const T &arg) {
++funcalls_;
return ConvertibleToBool (arg == val_);
}
private:
void operator= (EqualityPredicate&);
const T &val_;
};
template <class T>
std::size_t EqualityPredicate<T>::funcalls_;
/**************************************************************************/
// exercises std::remove() and std::remove_if()
template <class Iterator, class T, class Predicate>
void test_remove (int line,
const char *src, const char val, std::size_t nrem,
Iterator, NoIterator, const T*,
const Predicate*, RemoveTag tag)
{
static const char* const itname = type_name (Iterator (), (T*)0);
static const char* const fname = tag.use_predicate ?
fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
// compute the length of the source sequence
const std::size_t nsrc = std::strlen (src);
// construct a sequence of `nsrc' elements to pass to remove
T* const xsrc = T::from_char (src, nsrc + 1);
// construct an element to remove
T to_remove;
to_remove.data_.val_ = val;
// construct a predicate object (used with remove_if() only)
const Predicate pred (to_remove, 0);
// construct iterators pointing to the beginning and end
// of the source sequence
const Iterator first =
make_iter (xsrc, xsrc, xsrc + nsrc, Iterator ());
const Iterator last =
make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, Iterator ());
// zero out predicate counters
T::n_total_op_eq_ = 0;
// call remove() or remove_if()
const Iterator end = tag.use_predicate
? std::remove_if (first, last, pred)
: std::remove (first, last, to_remove);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (end);
// verify that the returned iterator is set as expected
bool success = end.cur_ == first.cur_ + (nsrc - nrem);
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) == first + %zu, got %zd",
__LINE__, fname, itname, src, val,
nsrc - nrem, end.cur_ - xsrc);
// verify that the value to be removed does not appear
// anywhere in the range [first, end) : p 25.2.7.2
success = true;
for (std::size_t i = 0; i != nsrc - nrem && success; ++i) {
success = UChar (val) != xsrc [i].data_.val_;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> "
"\"%{X=*.*}\"; expected element value %#c",
__LINE__, fname, itname, src, val,
int (nsrc), int (i), xsrc, src [i]);
}
// verify that the algorithm is stable: the relative order of the elements
// that are not removed remains unchanged : p 25.2.7.4
success = true;
for (std::size_t i = 1; i < nsrc - nrem && success; ++i) {
success = xsrc [i - 1].id_ < xsrc [i].id_;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> \"%{X=#*.*}\"; "
"unstable at offset %zu element ids: %d and %d",
__LINE__, fname, itname, src, val,
int (nsrc), int (i - 1), xsrc,
i - 1, xsrc [i - 1].id_, xsrc [i].id_);
}
// verify that the values of elements in the range [end, last)
// are unchanged
success = true;
for (std::size_t i = nsrc - nrem; i != nsrc && success; ++i) {
success = src [i] == xsrc [i].data_.val_;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> "
"\"%{X=*.*}\"; expected element value %#c",
__LINE__, fname, itname, src, val,
int (nsrc), int (i), xsrc, val);
}
// verify the number of applications of the predicate: p 25.2.7.5
if (tag.use_predicate) {
rw_assert (pred.funcalls_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"Predicate::operator() %zu times, %zu expected",
__LINE__, fname, itname, src, val,
pred.funcalls_, nsrc);
}
else {
rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"T::operator< %zu times, %zu expected",
__LINE__, fname, itname, src, val,
T::n_total_op_eq_, nsrc);
}
delete[] xsrc;
}
/**************************************************************************/
// exercises std::remove_copy()
template <class Iterator, class OutputIterator, class Predicate, class T>
void test_remove (int line,
const char *src, const char val, std::size_t nrem,
Iterator it, OutputIterator dummy, const T*,
const Predicate*, RemoveCopyTag tag)
{
static const char* const itname = type_name (it, (T*)0);
static const char* const fname = tag.use_predicate ?
fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xdst = T::from_char (src, nsrc);
T to_remove;
to_remove.data_.val_ = val;
const Predicate pred (to_remove, 0);
const Iterator first = make_iter (xsrc, xsrc, xsrc + nsrc, it);
const Iterator last = make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, it);
const OutputIterator result = make_iter (xdst, xdst, xdst + nsrc, dummy);
// zero out predicate counters
T::n_total_op_eq_ = 0;
const OutputIterator end = tag.use_predicate
? std::remove_copy_if (first, last, result, pred)
: std::remove_copy (first, last, result, to_remove);
// silence a bogus EDG eccp remark #550-D:
// variable "res" was set but never used
_RWSTD_UNUSED (end);
// verify that the returned iterator is set as expected p 25.2.7.8
bool success = end.cur_ == result.cur_ + (nsrc - nrem);
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) == first + %zu, got %zd",
__LINE__, fname, itname, src, val, nsrc - nrem, end.cur_ - xsrc);
// verify that the value to be removed does not appear anywhere
// in the range [result, end)
success = true;
for (std::size_t i = 0; i != nsrc - nrem && success; ++i) {
success = UChar (val) != xdst [i].data_.val_;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> "
"\"%{X=*.*}\"; expected element value %#c",
__LINE__, fname, itname, src, val,
int (nsrc - nrem), int (i), xdst, src [i]);
}
// verify that the algorithm is stable: the relative order of the elements
// that are not removed remains unchanged : p 25.2.7.10
success = true;
for (std::size_t i = 1; i < nsrc - nrem && success; ++i) {
success = xdst [i - 1].id_ < xdst [i].id_;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> \"%{X=#*.*}\"; "
"unstable at offset %zu: element ids: %d and %d",
__LINE__, fname, itname, src, val,
int (nsrc - nrem), int (i - 1), xdst,
i - 1, xdst [i - 1].id_, xdst [i].id_);
}
// verify the number of applications of the predicate p 25.2.7.9
if (tag.use_predicate) {
rw_assert (pred.funcalls_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"Predicate::operator() %zu times, %zu expected",
__LINE__, fname, itname, src, val,
pred.funcalls_, nsrc);
}
else {
rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"T::operator< %zu times, %zu expected",
__LINE__, fname, itname, src, val,
T::n_total_op_eq_, nsrc);
}
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
// exercises all four function templates
template <class Iterator1, class Iterator2, class T,
class Predicate, class Tag>
void test_remove (Iterator1 it1, Iterator2 it2,
const T*, const Predicate* pred, Tag tag)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
if (tag.fname_inx) { // remove_copy(), remove_copy_if()
rw_info (0, 0, 0,
"std::%s (%s, %2$s, %s, %s)",
tag.use_predicate ? "remove_copy_if" : "remove_copy",
it1name, it2name,
tag.use_predicate ? "UnaryPredicate" : "const T&");
}
else { // remove, remove_if()
rw_info (0, 0, 0,
"std::%s (%s, %2$s, %s)",
tag.use_predicate ? "remove_if" : "remove",
it1name,
tag.use_predicate ? "UnaryPredicate" : "const T&");
}
#define TEST(src, val, nremoved) \
test_remove (__LINE__, src, val, nremoved, it1, it2, (T*)0, pred, tag)
// +---------------------- original sequence
// | +------ element to remove
// | | +- number of removals
// | | |
// v v v
TEST ("", 'a', 0);
TEST ("a", 'a', 1);
TEST ("aa", 'a', 2);
TEST ("aaa", 'a', 3);
TEST ("aaaa", 'a', 4);
TEST ("aaaaa", 'a', 5);
TEST ("aaaaaa", 'a', 6);
TEST ("aaaaaaa", 'a', 7);
TEST ("aaaaaaaa", 'a', 8);
TEST ("aaaaaaaaa", 'a', 9);
TEST ("aaaaaaaaaa", 'a', 10);
TEST ("b", 'a', 0);
TEST ("bb", 'a', 0);
TEST ("ba", 'a', 1);
TEST ("ab", 'a', 1);
TEST ("abc", 'a', 1);
TEST ("bac", 'a', 1);
TEST ("bca", 'a', 1);
TEST ("aba", 'a', 2);
TEST ("abab", 'a', 2);
TEST ("ababa", 'a', 3);
TEST ("bababa", 'a', 3);
TEST ("bababab", 'a', 3);
TEST ("babababa", 'a', 4);
TEST ("baacaadaaeaa",'a', 8);
}
/**************************************************************************/
/* extern */ int rw_opt_no_remove; // --no-remove
/* extern */ int rw_opt_no_remove_if; // --no-remove_if
/* extern */ int rw_opt_no_remove_copy; // --no-remove_copy
/* extern */ int rw_opt_no_remove_copy_if; // --no-remove_copy_if
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class T, class Predicate, class Tag>
void test_remove (const T*, const Predicate* pred, Tag tag)
{
rw_info (0, 0, 0,
"template <class %s, class T> "
"std::%s (%1$s, %1$s, %s)",
"ForwardIterator",
tag.use_predicate ? "remove_if" : "remove",
tag.use_predicate ? "Predicate" : "const T&");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_remove (FwdIter<T>(), NoIterator (), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_remove (BidirIter<T>(), NoIterator (), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_remove (RandomAccessIter<T>(), NoIterator (), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T>
void test_remove (const T*)
{
const RemoveTag remove_tag = { false };
const RemoveTag remove_if_tag = { true };
if (rw_opt_no_remove) {
rw_note (0, __FILE__, __LINE__, "std::remove test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
test_remove((T*)0, pred, remove_tag);
}
if (rw_opt_no_remove_if) {
rw_note (0, __FILE__, __LINE__, "std::remove_if test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 1;
test_remove((T*)0, pred, remove_if_tag);
}
}
/**************************************************************************/
template <class InputIterator, class T, class Predicate, class Tag>
void test_remove_copy (const InputIterator& iter, const T*,
const Predicate* pred, Tag tag)
{
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_remove (iter, OutputIter<T>(0, 0, 0), (T*)0, pred, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_remove (iter, FwdIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_remove (iter, BidirIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_remove (iter, RandomAccessIter<T>(), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T, class Predicate, class Tag>
void test_remove_copy (const T*, const Predicate* pred, Tag tag)
{
rw_info (0, 0, 0,
"template "
"<class InputIterator, class OutputIterator, class T> "
"std::%s (InputIterator, InputIterator, "
"OutputIterator, %s)",
tag.use_predicate ? "remove_copy_if" : "remove_copy",
tag.use_predicate ? "Predicate" : "const T&");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_remove_copy (InputIter<T>(0, 0, 0), (T*)0, pred, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_remove_copy (FwdIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_remove_copy (BidirIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_remove_copy (RandomAccessIter<T>(), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T>
void test_remove_copy (const T* )
{
const RemoveCopyTag remove_copy_tag = { false };
const RemoveCopyTag remove_copy_if_tag = { true };
if (rw_opt_no_remove_copy) {
rw_note (0, __FILE__, __LINE__, "std::remove_copy test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
test_remove_copy((T*)0, pred, remove_copy_tag);
}
if (rw_opt_no_remove_copy_if) {
rw_note (0, __FILE__, __LINE__, "std::remove_copy_if test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 1;
test_remove_copy((T*)0, pred, remove_copy_if_tag);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_remove ((UserClass*)0);
test_remove_copy ((UserClass*)0);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.remove",
0 /* no comment */, run_test,
"|-no-remove# "
"|-no-remove_if# "
"|-no-remove_copy# "
"|-no-remove_copy_if# "
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_remove,
&rw_opt_no_remove_if,
&rw_opt_no_remove_copy,
&rw_opt_no_remove_copy_if,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,631 @@
/***************************************************************************
*
* 25.replace.cpp - test exercising 25.2.4 [lib.alg.replace]
*
* $Id: 25.replace.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for replace(), replace_copy()
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void replace (FwdIter<eq_comp<assign<base<> > > >,
FwdIter<eq_comp<assign<base<> > > >,
const eq_comp<assign<base<> > >&,
const eq_comp<assign<base<> > >&);
template
void replace_if (FwdIter<assign<base<> > > ,
FwdIter<assign<base<> > > ,
predicate<assign<base<> > > ,
const assign<base<> > &);
template
OutputIter<eq_comp<assign<base<> > > >
replace_copy (InputIter<eq_comp<assign<base<> > > >,
InputIter<eq_comp<assign<base<> > > >,
OutputIter<eq_comp<assign<base<> > > >,
const eq_comp<assign<base<> > >&,
const eq_comp<assign<base<> > >&);
template
OutputIter<assign<base<> > >
replace_copy_if (InputIter<assign<base<> > > ,
InputIter<assign<base<> > > ,
OutputIter<assign<base<> > > ,
predicate<assign<base<> > > ,
const assign<base<> > &);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// names of tested functions
const char* const fnames[] = { "replace", "replace_copy" };
const char* const fnames_if[] = { "replace_if", "replace_copy_if" };
// tags to select replace or replace_copy at compile time
struct ReplaceTag {
enum { fname_inx = 0 };
int use_predicate;
};
struct ReplaceCopyTag {
enum { fname_inx = 1 };
int use_predicate;
};
// used as a dummy template argument to test functions exercising replace()
// and replace_if() (to differentiate from replace_copy() and replace_copy_if())
struct NoIterator { };
const char* type_name (NoIterator, const UserClass*)
{
return 0;
}
/**************************************************************************/
// predicate used as an argument to replace_if() and replace_copy_if()
template <class T>
struct EqualityPredicate
{
static std::size_t funcalls_;
EqualityPredicate (const T &val, int /* dummy */)
: val_ (val) {
funcalls_ = 0;
}
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
ConvertibleToBool operator() (const T &arg) {
++funcalls_;
return ConvertibleToBool (arg == val_);
}
private:
void operator= (EqualityPredicate&);
const T &val_;
};
template <class T>
std::size_t EqualityPredicate<T>::funcalls_;
/**************************************************************************/
// exercises std::replace() and std::replace_if()
template <class Iterator, class T, class Predicate>
void test_replace (int line,
const char *src, // source sequence
char val, // value to replace
char new_val, // value to replace it with
Iterator dummy, // not used
NoIterator,
const T*,
const Predicate*,
ReplaceTag tag) // replace() or replace_if()
{
static const char* const itname = type_name (Iterator (), (T*)0);
static const char* const fname = tag.use_predicate ?
fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
// compute the length of the source sequence
const std::size_t nsrc = std::strlen (src);
// construct a sequence of `nsrc' elements to pass to replace
// (make sure there's always at least 1 element, even if the
// sequence is otherwise empty, to avoid undefined behavior
// when de-referencing xsrc[0] in inactive diagnostic messages)
T* const xsrc = T::from_char (src, nsrc + 1);
T* const xsrc_end = xsrc + nsrc;
// construct an element to replace
T to_replace;
to_replace.data_.val_ = val;
// construct an element to replace it with
T replace_with;
replace_with.data_.val_ = new_val;
// construct a predicate object (used with replace_if() only)
const Predicate pred (to_replace, 0);
// construct iterators pointing to the beginning and end
// of the source sequence
const Iterator first = make_iter (xsrc, xsrc, xsrc_end, dummy);
const Iterator last = make_iter (xsrc_end, xsrc_end, xsrc_end, dummy);
// zero out predicate counters
T::n_total_op_eq_ = 0;
// call replace() or replace_if()
if (tag.use_predicate)
std::replace_if (first, last, pred, replace_with);
else
std::replace (first, last, to_replace, replace_with);
// verify that the value to be replaced has been replaced
// with the replacement value
bool success = true;
std::size_t i = 0;
for ( ; i != nsrc; ++i) {
success = to_replace.data_.val_ != xsrc [i].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c, %#c) ==> "
"\"%{X=*.*}\"; unexpected element value %#c",
__LINE__, fname, itname, src, val, new_val,
int (nsrc), int (i), xsrc, src [i]);
// check the id (not just the value) of the matching element
// to make sure it has really been replaced
for (i = 0; i != nsrc; ++i) {
success =
val != src [i]
|| val == src [i]
&& replace_with.origin_ == xsrc [i].origin_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c, %#c) ==> "
"\"%{X=#*.*}\"; failed to replace element %zu: "
"origin %d (%d, %d), expected %d (%d)",
__LINE__, fname, itname, src, val, new_val,
int (nsrc), int (i), xsrc,
i, xsrc [i].origin_, xsrc [i].id_, xsrc [i].src_id_,
replace_with.origin_, replace_with.id_);
// verify the number of applications of the predicate: p 25.2.4.3
if (tag.use_predicate) {
rw_assert (pred.funcalls_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"Predicate::operator() %zu times, %zu expected",
__LINE__, fname, itname, src, val,
pred.funcalls_, nsrc);
}
else {
rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"T::operator< %zu times, %zu expected",
__LINE__, fname, itname, src, val,
T::n_total_op_eq_, nsrc);
}
delete[] xsrc;
}
/**************************************************************************/
// exercises std::replace_copy()
template <class Iterator, class OutputIterator, class T, class Predicate>
void test_replace (int line,
const char *src, // source sequence
char val, // value to replace
char new_val, // value to replace it with
Iterator it,
OutputIterator dummy,
const T*,
const Predicate*,
ReplaceCopyTag tag) // replace_copy or replace_copy_if
{
static const char* const itname = type_name (it, (T*)0);
static const char* const fname = tag.use_predicate ?
fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
const std::size_t nsrc = std::strlen (src);
// construct a sequence of `nsrc' elements to pass to replace
// (make sure there's always at least 1 element, even if the
// sequence is otherwise empty, to avoid undefined behavior
// when de-referencing xsrc[0] in inactive diagnostic messages)
T* const xsrc = T::from_char (src, nsrc + 1);
T* const xdst = T::from_char (src, nsrc + 1);
T* const xsrc_end = xsrc + nsrc;
T* const xdst_end = xdst + nsrc;
T to_replace;
to_replace.data_.val_ = val;
T replace_with;
replace_with.data_.val_ = new_val;
const Predicate pred (to_replace, 0);
const Iterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const Iterator last = make_iter (xsrc_end, xsrc_end, xsrc_end, it);
const OutputIterator result = make_iter (xdst, xdst, xdst_end, dummy);
// zero out predicate counters
T::n_total_op_eq_ = 0;
const OutputIterator end = tag.use_predicate
? std::replace_copy_if (first, last, result, pred, replace_with)
: std::replace_copy (first, last, result, to_replace, replace_with);
// verify that the returned iterator is set as expected
rw_assert (end.cur_ == result.cur_ + nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) == result + %zu, got %td",
__LINE__, fname, itname, src, val, nsrc, end.cur_ - xdst);
// verify that the value to be replaced does not appear anywhere
// in the range [result, end)
bool success = true;
std::size_t i = 0;
for ( ; i != nsrc; ++i) {
typedef unsigned char UChar;
success = UChar (val) != xdst [i].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) ==> "
"\"%{X=*.*}\"; unexpected element value %#c",
__LINE__, fname, itname, src, val,
int (nsrc), int (i), xdst, src [i]);
// check the id (not just the value) of the matching element
// to make sure it has really been copied
for (i = 0; i != nsrc; ++i) {
success =
val != src [i]
|| val == src [i]
&& replace_with.origin_ == xdst [i].origin_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c, %#c) ==> "
"\"%{X=*.*}\"; failed to copy and replace element %zu: "
"origin %d (%d, %d), expected %d (%d)",
__LINE__, fname, itname, src, val, new_val,
int (nsrc), int (i), xdst,
i, xdst [i].origin_, xdst [i].id_, xdst [i].src_id_,
replace_with.origin_, replace_with.id_);
// verify the number of applications of the predicate: p 25.2.4.7
if (tag.use_predicate) {
rw_assert (pred.funcalls_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"Predicate::operator() %zu times, %zu expected",
__LINE__, fname, itname, src, val,
pred.funcalls_, nsrc);
}
else {
rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
"line %d: %s<%s>(\"%s\", ..., %#c) called "
"T::operator< %zu times, %zu expected",
__LINE__, fname, itname, src, val,
T::n_total_op_eq_, nsrc);
}
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
// exercises all four function templates
template <class Iterator1, class Iterator2, class T,
class Predicate, class Tag>
void test_replace (Iterator1 it1, Iterator2 it2, const T*,
const Predicate* pred, Tag tag)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
if (tag.fname_inx) { // replace_copy(), replace_copy_if()
rw_info (0, 0, 0,
"std::%s (%s, %s, %s, %s, const T&)",
tag.use_predicate ? "replace_copy_if" : "replace_copy",
it1name, it1name, it2name,
tag.use_predicate ? "UnaryPredicate" : "const T&");
}
else { // replace, replace_if()
rw_info (0, 0, 0,
"std::%s (%s, %s, %s, const T&)",
tag.use_predicate ? "replace_if" : "replace",
it1name, it1name,
tag.use_predicate ? "UnaryPredicate" : "const T&");
}
#define TEST(src, val, new_val) \
test_replace (__LINE__, src, val, new_val, it1, it2, (T*)0, pred, tag)
// +----------------------- original sequence
// | +------- value to replace
// | | +- value to replace it with
// | | |
// v v v
TEST ("", 'a', 'b');
TEST ("a", 'a', 'b');
TEST ("aa", 'a', 'b');
TEST ("aaa", 'a', 'b');
TEST ("aaaa", 'a', 'b');
TEST ("aaaaa", 'a', 'b');
TEST ("aaaaaa", 'a', 'b');
TEST ("aaaaaaa", 'a', 'b');
TEST ("aaaaaaaa", 'a', 'b');
TEST ("aaaaaaaaa", 'a', 'b');
TEST ("aaaaaaaaaa", 'a', 'b');
TEST ("b", 'a', 'b');
TEST ("bb", 'a', 'b');
TEST ("ba", 'a', 'b');
TEST ("ab", 'a', 'b');
TEST ("abc", 'a', 'b');
TEST ("bac", 'a', 'b');
TEST ("bca", 'a', 'b');
TEST ("aba", 'a', 'b');
TEST ("abab", 'a', 'b');
TEST ("ababa", 'a', 'b');
TEST ("bababa", 'a', 'b');
TEST ("bababab", 'a', 'b');
TEST ("babababa", 'a', 'b');
TEST ("bbbbbbbbb", 'a', 'b');
}
/**************************************************************************/
/* extern */ int rw_opt_no_replace; // --no-replace
/* extern */ int rw_opt_no_replace_if; // --no-replace_if
/* extern */ int rw_opt_no_replace_copy; // --no-replace_copy
/* extern */ int rw_opt_no_replace_copy_if; // --no-replace_copy_if
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T, class Predicate, class Tag>
void test_replace (const T* , const Predicate* pred, Tag tag)
{
rw_info (0, 0, 0,
"template <class ForwardIterator, class T> "
"std::%s (ForwardIterator, ForwardIterator, "
"%s, const T&)",
tag.use_predicate ? "replace_if" : "replace",
tag.use_predicate ? "Predicate" : "const T&");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_replace (FwdIter<T>(), NoIterator (), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_replace (BidirIter<T>(), NoIterator (), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_replace (RandomAccessIter<T>(), NoIterator (), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T>
void test_replace (const T* )
{
const ReplaceTag replace_tag = { false };
const ReplaceTag replace_if_tag = { true };
if (rw_opt_no_replace) {
rw_note (0, __FILE__, __LINE__, "std::replace test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
test_replace((T*)0, pred, replace_tag);
}
if (rw_opt_no_replace_if) {
rw_note (0, __FILE__, __LINE__, "std::replace_if test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 1;
test_replace((T*)0, pred, replace_if_tag);
}
}
/**************************************************************************/
template <class InputIterator, class T, class Predicate, class Tag>
void test_replace_copy (const InputIterator& iter, const T*,
const Predicate* pred, Tag tag)
{
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_replace (iter, OutputIter<T>(0, 0, 0), (T*)0, pred, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_replace (iter, FwdIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_replace (iter, BidirIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_replace (iter, RandomAccessIter<T>(), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T, class Predicate, class Tag>
void test_replace_copy (const T*, const Predicate* pred, Tag tag)
{
rw_info (0, 0, 0,
"template "
"<class InputIterator, class OutputIterator, class T> "
"std::%s (InputIterator, InputIterator, "
"OutputIterator, %s, const T&)",
tag.use_predicate ? "replace_copy_if" : "replace_copy",
tag.use_predicate ? "Predicate" : "const T&");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_replace_copy (InputIter<T>(0, 0, 0), (T*)0, pred, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_replace_copy (FwdIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_replace_copy (BidirIter<T>(), (T*)0, pred, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_replace_copy (RandomAccessIter<T>(), (T*)0, pred, tag);
}
}
/**************************************************************************/
template <class T>
void test_replace_copy (const T* )
{
const ReplaceCopyTag replace_copy_tag = { false };
const ReplaceCopyTag replace_copy_if_tag = { true };
if (rw_opt_no_replace_copy) {
rw_note (0, __FILE__, __LINE__, "std::replace_copy test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
test_replace_copy ((T*)0, pred, replace_copy_tag);
}
if (rw_opt_no_replace_copy_if) {
rw_note (0, __FILE__, __LINE__, "std::replace_copy_if test disabled");
}
else {
const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*)1;
test_replace_copy ((T*)0, pred, replace_copy_if_tag);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_replace ((UserClass*)0);
test_replace_copy ((UserClass*)0);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.replace",
0 /* no comment */,
run_test,
"|-no-replace# "
"|-no-replace_if# "
"|-no-replace_copy# "
"|-no-replace_copy_if# "
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_replace,
&rw_opt_no_replace_if,
&rw_opt_no_replace_copy,
&rw_opt_no_replace_copy_if,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,415 @@
/***************************************************************************
*
* 25.reverse.cpp - test exercising 25.2.9 [lib.alg.reverse]
*
* $Id: 25.reverse.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for reverse, reverse_copy
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void reverse (BidirIter<assign<base<cpy_ctor> > >,
BidirIter<assign<base<cpy_ctor> > >);
template
OutputIter<eq_comp<assign<base<> > > >
reverse_copy (BidirIter<eq_comp<assign<base<> > > >,
BidirIter<eq_comp<assign<base<> > > >,
OutputIter<eq_comp<assign<base<> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// tags to select reverse or reverse_copy at compile time
struct ReverseTag {
enum { fname_inx = 0 };
int dummy;
};
struct ReverseCopyTag {
enum { fname_inx = 1 };
int dummy;
};
// used as a dummy template argument to test functions exercising reverse()
// and reverse_if() (to differentiate from reverse_copy() and reverse_copy_if())
struct NoIterator { };
const char* type_name (NoIterator, const UserClass*)
{
return 0;
}
/**************************************************************************/
unsigned iter_swap_calls;
_RWSTD_NAMESPACE (std) {
_RWSTD_SPECIALIZED_FUNCTION
void iter_swap (BidirIter<UserClass> i, BidirIter<UserClass> j)
{
++iter_swap_calls;
const int tmp = (*i).data_.val_;
(*i).data_.val_ = (*j).data_.val_;
(*j).data_.val_ = tmp;
}
_RWSTD_SPECIALIZED_FUNCTION
void iter_swap (RandomAccessIter<UserClass> i, RandomAccessIter<UserClass> j)
{
++iter_swap_calls;
const int tmp = (*i).data_.val_;
(*i).data_.val_ = (*j).data_.val_;
(*j).data_.val_ = tmp;
}
} // namespace std
/**************************************************************************/
// exercises std::reverse()
template <class Iterator, class T>
void test_reverse (int line,
const char *src,
Iterator dummy, NoIterator, const T*, ReverseTag)
{
static const char* const itname = type_name (dummy, (T*)0);
const char* const fname = "reverse";
// compute the length of the source sequence
const std::size_t nsrc = std::strlen (src);
// construct a sequence of `nsrc' elements to pass to reverse
T* const xsrc = T::from_char (src, nsrc);
// construct iterators pointing to the beginning and end
// of the source sequence
const Iterator first = make_iter (xsrc, xsrc, xsrc + nsrc, dummy);
const Iterator last = make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, dummy);
// zero out the iter_swap() call counter
iter_swap_calls = 0;
// call reverse()
std::reverse (first, last);
bool success = true;
std::size_t i = 0;
// verify that the sequence was correctly reversed and that it was
// done by swapping elements i.e., not simply by copying them over
for ( ; i != nsrc; ++i) {
typedef unsigned char UChar;
success = UChar (src [i]) == xsrc [nsrc - i - 1].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ...) ==> "
"\"%{X=*.*}\"; unexpected element value %#c at offset %zu",
__LINE__, fname, itname, src,
int (nsrc), int (i), xsrc,
xsrc [nsrc - i - 1].data_.val_, i);
const std::size_t iter_swap_expect = nsrc / 2;
success = iter_swap_calls == iter_swap_expect;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ...); called iter_swap() "
"%zu times, %zu expected",
__LINE__, fname, itname, src,
iter_swap_calls, iter_swap_expect);
delete[] xsrc;
}
/**************************************************************************/
// exercises std::reverse_copy()
template <class Iterator, class OutputIterator, class T>
void test_reverse (int line,
const char *src,
Iterator& it, OutputIterator& ,
const T*, ReverseCopyTag)
{
static const char* const itname = type_name (it, (T*)0);
const char* const fname = "reverse_copy";
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xdst = T::from_char (src, nsrc);
const Iterator first (xsrc, xsrc, xsrc + nsrc);
const Iterator last (xsrc + nsrc, xsrc, xsrc + nsrc);
const OutputIterator result (xdst, xdst, xdst + nsrc);
std::size_t last_n_op_assign = T::n_total_op_assign_;
const OutputIterator end = std::reverse_copy (first, last, result);
// verify that the returned iterator is set as expected
bool success = end.cur_ == result.cur_ + nsrc;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ...) == result + %zu, got %td",
__LINE__, fname, itname, src, nsrc, end.cur_ - xdst);
// verify that the sequence was correctly reversed
std::size_t i = 0;
for ( ; i != nsrc; ++i) {
typedef unsigned char UChar;
success = UChar (src [i]) == xdst [nsrc - i - 1].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ...) ==> "
"\"%{X=*.*}\"; unexpected element value %#c at offset %zu",
__LINE__, fname, itname, src,
int (nsrc), int (i), xsrc,
xdst [nsrc - i - 1].data_.val_, i);
success = T::n_total_op_assign_ - last_n_op_assign == nsrc;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", ...); called operator=() "
"%zu times, %zu expected",
__LINE__, fname, itname, src,
T::n_total_op_assign_ - last_n_op_assign, nsrc);
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
// exercises all four function templates
template <class Iterator1, class Iterator2, class T, class Tag>
void test_reverse (Iterator1 it1, Iterator2 it2, const T*, Tag tag)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
if (tag.fname_inx) { // reverse_copy()
rw_info (0, 0, 0, "std::reverse_copy (%s, %1$s, %s)", it1name, it2name);
}
else { // reverse()
rw_info (0, 0, 0, "std::reverse (%s, %1$s)", it1name);
}
#define TEST(src) \
test_reverse (__LINE__, src, it1, it2, (T*)0, tag)
TEST ("");
TEST ("a");
TEST ("ab");
TEST ("abc");
TEST ("abcd");
TEST ("abcde");
TEST ("abcdef");
TEST ("abcdefg");
TEST ("abcdefgh");
TEST ("abcdefghi");
TEST ("abcdefghij");
TEST ("abcdefghijk");
TEST ("abcdefghijkl");
TEST ("abcdefghijklm");
TEST ("abcdefghijklmn");
TEST ("abcdefghijklmno");
TEST ("abcdefghijklmnop");
TEST ("abcdefghijklmnopq");
TEST ("abcdefghijklmnopqr");
TEST ("abcdefghijklmnopqrs");
TEST ("abcdefghijklmnopqrst");
TEST ("abcdefghijklmnopqrstu");
TEST ("abcdefghijklmnopqrstuv");
TEST ("abcdefghijklmnopqrstuvw");
TEST ("abcdefghijklmnopqrstuvwx");
TEST ("abcdefghijklmnopqrstuvwxy");
TEST ("abcdefghijklmnopqrstuvwxyz");
}
/**************************************************************************/
/* extern */ int rw_opt_no_reverse; // --no-reverse
/* extern */ int rw_opt_no_reverse_copy; // --no-reverse_copy
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T, class Tag>
void test_reverse(const T*, Tag tag)
{
rw_info (0, 0, 0,
"template <class %s> %1$s std::reverse (%1$s, %1$s)",
"BidirectionalIterator");
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_reverse (BidirIter<T>(), NoIterator (), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_reverse (RandomAccessIter<T>(), NoIterator (), (T*)0, tag);
}
}
/**************************************************************************/
template <class ReverseIterator, class T, class Tag>
void test_reverse_copy (ReverseIterator it, const T*, Tag tag)
{
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_reverse (it, OutputIter<T>(0, 0, 0), (T*)0, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_reverse (it, FwdIter<T>(), (T*)0, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_reverse (it, BidirIter<T>(), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_reverse (it, RandomAccessIter<T>(), (T*)0, tag);
}
}
/**************************************************************************/
template <class T, class Tag>
void test_reverse_copy (const T*, Tag tag)
{
rw_info (0, 0, 0,
"template <class %s, class %s> %2$s "
"std::reverse_copy (%1$s, %1$s, %2$s)",
"BidirectionalIterator", "OutputIterator");
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_reverse_copy (ConstBidirIter<T>(), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_reverse_copy (ConstRandomAccessIter<T>(), (T*)0, tag);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
const ReverseTag reverse_tag = { false };
const ReverseCopyTag reverse_copy_tag = { true };
if (rw_opt_no_reverse) {
rw_note (0, __FILE__, __LINE__, "std::reverse test disabled");
}
else {
test_reverse((UserClass*)0, reverse_tag);
}
if (rw_opt_no_reverse_copy) {
rw_note (0, __FILE__, __LINE__, "std::reverse_copy test disabled");
}
else {
test_reverse_copy((UserClass*)0, reverse_copy_tag);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.reverse",
0 /* no comment */, run_test,
"|-no-reverse# "
"|-no-reverse_copy# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_reverse,
&rw_opt_no_reverse_copy,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,453 @@
/***************************************************************************
*
* 25.rotate.cpp - test exercising 25.2.10 [lib.alg.rotate]
*
* $Id: 25.rotate.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for rotate, rotate_copy
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
rotate (FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >);
template
OutputIter<assign<base<cpy_ctor> > >
rotate_copy (FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >,
OutputIter<assign<base<cpy_ctor> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// tags to select rotate or rotate_copy at compile time
struct RotateTag {
enum { fname_inx = 0 };
int dummy;
};
struct RotateCopyTag {
enum { fname_inx = 1 };
int dummy;
};
// used as a dummy template argument to test functions exercising rotate()
// (to differentiate from rotate_copy())
struct NoIterator { };
const char* type_name (NoIterator, const UserClass*)
{
return 0;
}
/**************************************************************************/
unsigned iter_swap_calls;
_RWSTD_NAMESPACE (std) {
_RWSTD_SPECIALIZED_FUNCTION
void iter_swap (FwdIter<UserClass> i, FwdIter<UserClass> j)
{
++iter_swap_calls;
const int tmp = (*i).data_.val_;
(*i).data_.val_ = (*j).data_.val_;
(*j).data_.val_ = tmp;
}
_RWSTD_SPECIALIZED_FUNCTION
void iter_swap (BidirIter<UserClass> i, BidirIter<UserClass> j)
{
++iter_swap_calls;
const int tmp = (*i).data_.val_;
(*i).data_.val_ = (*j).data_.val_;
(*j).data_.val_ = tmp;
}
_RWSTD_SPECIALIZED_FUNCTION
void iter_swap (RandomAccessIter<UserClass> i, RandomAccessIter<UserClass> j)
{
++iter_swap_calls;
const int tmp = (*i).data_.val_;
(*i).data_.val_ = (*j).data_.val_;
(*j).data_.val_ = tmp;
}
} // namespace std
/**************************************************************************/
// exercises std::rotate()
template <class Iterator, class T>
void test_rotate (int line,
const char *src,
std::size_t midnsrc,
Iterator it, NoIterator, const T*, RotateTag)
{
static const char* const itname = type_name (it, (T*)0);
const char* const fname = "rotate";
// compute the length of the source sequence
const std::size_t nsrc = std::strlen (src);
// construct a sequence of `nsrc' elements to pass to reverse
T* const xsrc = T::from_char (src, nsrc);
// construct iterators pointing to the beginning and end
// of the source sequence
const Iterator first = make_iter (xsrc, xsrc, xsrc + nsrc, it);
const Iterator middle = make_iter (xsrc + midnsrc, xsrc, xsrc + nsrc, it);
const Iterator last = make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, it);
// zero out the iter_swap() call counter
iter_swap_calls = 0;
// call rotate()
std::rotate (first, middle, last);
bool success = true;
std::size_t i = 0;
std::size_t xpos = 0;
// verify that the sequence was correctly reversed and that it was
// done by swapping elements i.e., not simply by copying them over
for ( ; i != nsrc; ++i) {
xpos = (i + (nsrc - midnsrc)) % nsrc;
typedef unsigned char UChar;
success = UChar (src [i]) == xsrc [xpos].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", %zu, ...) ==> "
"\"%{X=*.*}\"; unexpected element value %#c at %zu",
__LINE__, fname, itname, src, midnsrc,
int (nsrc), int (i), xsrc, xsrc [xpos].data_.val_, i);
success = iter_swap_calls <= nsrc;
rw_assert (success, 0, line,
"line %d: %s<%s>(\"%s\", %zu, ...); called iter_swap() "
"%zu times, expected no more than %zu",
__LINE__, fname, itname, src, midnsrc,
iter_swap_calls, nsrc);
delete[] xsrc;
}
/**************************************************************************/
// exercises std::rotate_copy()
template <class Iterator, class OutputIterator, class T>
void test_rotate (int line,
const char *src,
std::size_t midnsrc,
Iterator it, OutputIterator dummy,
const T*, RotateCopyTag)
{
static const char* const it1name = type_name (it, (T*)0);
static const char* const it2name = type_name (dummy, (T*)0);
const char* const fname = "rotate_copy";
const std::size_t nsrc = std::strlen (src);
T* const xsrc = T::from_char (src, nsrc);
T* const xdst = T::from_char (src, nsrc);
const Iterator first (xsrc, xsrc, xsrc + nsrc);
const Iterator middle (xsrc + midnsrc, xsrc, xsrc + nsrc);
const Iterator last (xsrc + nsrc, xsrc, xsrc + nsrc);
const OutputIterator result (xdst, xdst, xdst + nsrc);
std::size_t last_n_op_assign = T::n_total_op_assign_;
const OutputIterator end = std::rotate_copy (first, middle, last, result);
// verify that the returned iterator is set as expected
bool success = end.cur_ == result.cur_ + nsrc;
rw_assert (success, 0, line,
"line %d: %s<%s, %s>(\"%s\", %zu, ...) == result + %zu, got %td",
__LINE__, fname, it1name, it2name, src, midnsrc,
nsrc, end.cur_ - xdst);
// verify that the sequence was correctly rotated
std::size_t i = 0;
std::size_t xpos = 0;
for ( ; i != nsrc; ++i) {
xpos = (i + (nsrc - midnsrc)) % nsrc;
typedef unsigned char UChar;
success = UChar (src [i]) == xdst [xpos].data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"line %d: %s<%s, %s>(\"%s\", %zu, ...) ==> "
"\"%{X=*.*}\"; unexpected element value %#c at %zu",
__LINE__, fname, it1name, it2name, src, midnsrc,
int (nsrc), int (i), xsrc, xdst [xpos].data_.val_, i);
success = T::n_total_op_assign_ - last_n_op_assign == nsrc;
rw_assert (success, 0, line,
"line %d: %s<%s, %s>(\"%s\", %zu, ...); called operator=() "
"%zu times, %zu expected",
__LINE__, fname, it1name, it2name, src, midnsrc,
T::n_total_op_assign_ - last_n_op_assign, nsrc);
delete[] xsrc;
delete[] xdst;
}
/**************************************************************************/
// exercises all two function templates
template <class Iterator1, class Iterator2, class T, class Tag>
void test_rotate (Iterator1 it1, Iterator2 it2, const T*, Tag tag)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
if (tag.fname_inx) { // rotate_copy()
rw_info (0, 0, 0,
"std::rotate_copy (%s, %1$s, %1$s, %s)",
it1name, it2name);
}
else { // reverse, rotate()
rw_info (0, 0, 0,
"std::rotate (%s, %1$s, %1$s)",
it1name);
}
#define TEST(src, middle) \
test_rotate (__LINE__, src, middle, it1, it2, (T*)0, tag)
TEST ("", 0);
TEST ("a", 0);
TEST ("ab", 1);
TEST ("abc", 1);
TEST ("abcd", 2);
TEST ("abcde", 2);
TEST ("abcdef", 3);
TEST ("abcdefg", 3);
TEST ("abcdefgh", 4);
TEST ("abcdefghi", 4);
TEST ("abcdefghij", 5);
TEST ("abcdefghijk", 0);
TEST ("abcdefghijk", 1);
TEST ("abcdefghijk", 2);
TEST ("abcdefghijk", 3);
TEST ("abcdefghijk", 4);
TEST ("abcdefghijk", 5);
TEST ("abcdefghijk", 6);
TEST ("abcdefghijk", 7);
TEST ("abcdefghijk", 8);
TEST ("abcdefghijk", 9);
TEST ("abcdefghijk", 10);
}
/**************************************************************************/
/* extern */ int rw_opt_no_rotate; // --no-rotate
/* extern */ int rw_opt_no_rotate_copy; // --no-rotate_copy
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T, class Tag>
void test_rotate (const T*, Tag tag)
{
rw_info (0, 0, 0,
"template <class %s> std::rotate (%1$s, %1$s, %1$s)",
"ForwardIterator");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_rotate (FwdIter<T>(), NoIterator (), (T*)0, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_rotate (BidirIter<T>(), NoIterator (), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_rotate (RandomAccessIter<T>(), NoIterator (), (T*)0, tag);
}
}
/**************************************************************************/
template <class RotateIterator, class T, class Tag>
void test_rotate_copy (RotateIterator it, const T*, Tag tag)
{
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_rotate (it, OutputIter<T>(0, 0, 0), (T*)0, tag);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_rotate (it, FwdIter<T>(), (T*)0, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_rotate (it, BidirIter<T>(), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_rotate (it, RandomAccessIter<T>(), (T*)0, tag);
}
}
/**************************************************************************/
template <class T, class Tag>
void test_rotate_copy(const T*, Tag tag)
{
rw_info (0, 0, 0,
"template <class %s, class %s> %2$s "
"std::rotate_copy (%1$s, %1$s, %1$s, %2$s)",
"ForwardIterator", "OutputIterator");
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_rotate_copy (ConstFwdIter<T>(), (T*)0, tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_rotate_copy (ConstBidirIter<T>(), (T*)0, tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_rotate_copy (ConstRandomAccessIter<T>(), (T*)0, tag);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
const RotateTag rotate_tag = { false };
const RotateCopyTag rotate_copy_tag = { true };
if (rw_opt_no_rotate) {
rw_note (0, __FILE__, __LINE__, "std::rotate test disabled");
}
else {
test_rotate((UserClass*)0, rotate_tag);
}
if (rw_opt_no_rotate_copy) {
rw_note (0, __FILE__, __LINE__, "std::rotate_copy test disabled");
}
else {
test_rotate_copy((UserClass*)0, rotate_copy_tag);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.rotate",
0 /* no comment */, run_test,
"|-no-rotate# "
"|-no-rotate_copy# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_rotate,
&rw_opt_no_rotate_copy,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,710 @@
/***************************************************************************
*
* 25.search.cpp - test exercising 25.1.9 [lib.alg.search]
*
* $Id: 25.search.cpp 510970 2007-02-23 14:57:45Z 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-2005 Rogue Wave Software.
*
**************************************************************************/
#include <algorithm> // for search, search_n
#include <cstring> // for strlen
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
// instantiate each algorithm on all kinds of iterators
// it is required to work with (the algorithm may delegate
// to different implementations specialized for each kind
// of iterator)
template
FwdIter<eq_comp<base<> > >
search (FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >);
template
BidirIter<eq_comp<base<> > >
search (BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >);
template
RandomAccessIter<eq_comp<base<> > >
search (RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >);
template
FwdIter<eq_comp<base<> > >
search (FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
template
BidirIter<eq_comp<base<> > >
search (BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
template
RandomAccessIter<eq_comp<base<> > >
search (RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
binary_predicate<eq_comp<base<> > >);
template
FwdIter<eq_comp<base<> > >
search_n (FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&);
template
BidirIter<eq_comp<base<> > >
search_n (BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&);
template
RandomAccessIter<eq_comp<base<> > >
search_n (RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&);
template
FwdIter<eq_comp<base<> > >
search_n (FwdIter<eq_comp<base<> > >,
FwdIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&,
binary_predicate<eq_comp<base<> > >);
template
BidirIter<eq_comp<base<> > >
search_n (BidirIter<eq_comp<base<> > >,
BidirIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&,
binary_predicate<eq_comp<base<> > >);
template
RandomAccessIter<eq_comp<base<> > >
search_n (RandomAccessIter<eq_comp<base<> > >,
RandomAccessIter<eq_comp<base<> > >,
Size<int>, const eq_comp<base<> >&,
binary_predicate<eq_comp<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T, class U>
struct EqualityPredicate
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class
// from being default constructible
EqualityPredicate (T* /* dummy */, U* /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
class ConvertibleToBool {
bool result_;
public:
ConvertibleToBool (bool res): result_ (res) { /* empty */ }
operator bool() const { return result_; }
};
ConvertibleToBool operator() (const T &x, const U &y) /* non-const */ {
++funcalls_;
return x == y;
}
};
template <class T, class U>
std::size_t EqualityPredicate<T, U>::funcalls_;
/**************************************************************************/
// tags to select predicate or non-predicate versions
template <class T>
struct PredicateTag {
enum { pred_inx = 1 };
int dummy;
typedef EqualityPredicate<T, T> Predicate;
};
template <class T>
struct NonPredicateTag {
enum { pred_inx = 0 };
int dummy;
// dummy predicate to be used for non-predicate
// versions as a placeholder
struct DummyPredicate {
DummyPredicate(T*, T*) {}
bool operator() (const T& , const T& ) {
return false;
}
static std::size_t funcalls_;
};
typedef DummyPredicate Predicate;
};
template <class T>
std::size_t NonPredicateTag<T>::DummyPredicate::funcalls_;
#if defined (_MSC_VER) && _MSC_VER <= 1300
// to prevent MSVC 7.0 error LNK2001: unresolved external symbol "public:
// static unsigned int
// NonPredicateTag<struct UserClass>::DummyPredicate::funcalls_"
std::size_t NonPredicateTag<UserClass>::DummyPredicate::funcalls_;
#endif
/**************************************************************************/
// exercises std::search()
template
<class ForwardIterator1, class ForwardIterator2, class T, class PredTag>
void test_search (int line,
const char *seq1, const char *seq2,
std::size_t off,
ForwardIterator1 it1, ForwardIterator2 it2,
const T* , PredTag pred_tag)
{
const char* const fname = "search";
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
static const char* const predname =
pred_tag.pred_inx ? "BinaryPredicate" : "operator <()";
const std::size_t nseq1 = std::strlen (seq1);
const std::size_t nseq2 = std::strlen (seq2);
// construct a sequence of `nsrc' elements to pass to search
T* const xseq1 = T::from_char (seq1, nseq1);
T* const xseq2 = T::from_char (seq2, nseq2);
// construct iterators pointing to the beginning and end
// of the source sequences
const ForwardIterator1 first1 =
make_iter (xseq1, xseq1, xseq1 + nseq1, it1);
const ForwardIterator1 last1 =
make_iter (xseq1 + nseq1, xseq1, xseq1 + nseq1, it1);
const ForwardIterator1 expected = _RWSTD_SIZE_MAX == off ?
last1
: make_iter (xseq1 + off, xseq1, xseq1 + off, it1);
_RWSTD_UNUSED (expected);
const ForwardIterator2 first2 =
make_iter (xseq2, xseq2, xseq2 + nseq2, it2);
const ForwardIterator2 last2 =
make_iter (xseq2 + nseq2, xseq2, xseq2 + nseq2, it2);
T::n_total_op_eq_ = 0;
PredTag::Predicate::funcalls_ = 0;
typename PredTag::Predicate pred(0, 0);
const ForwardIterator1 result = pred_tag.pred_inx ?
std::search (first1, last1, first2, last2, pred)
: std::search (first1, last1, first2, last2);
_RWSTD_UNUSED (result);
// 25.1.9, p2:
// check the returned iterator
rw_assert (result.cur_ == expected.cur_, 0, line,
"std::%s<%s, %s%{?}, %s%{;}> (\"%s\", ..., \"%s\") "
"found subsequence at %td, expected at %{?}end%{;}%zu%{;}",
fname, it1name, it2name, pred_tag.pred_inx, predname,
seq1, seq2, result.cur_ - first1.cur_,
_RWSTD_SIZE_MAX == off, off);
// 25.1.9, p3:
// Complexity: At most (last1 <20> first1) * (last2 <20> first2)
// applications of the corresponding predicate or operator
const std::size_t max_op_eq = nseq1 * nseq2;
const std::size_t op_called = pred_tag.pred_inx ?
PredTag::Predicate::funcalls_
: T::n_total_op_eq_;
rw_assert (op_called <= max_op_eq, 0, line,
"std::%s<%s, %s%{?}, %s%{;}> (\"%s\", ..., \"%s\") "
"called %s %zu times, expected no more than %zu",
fname, it1name, it2name, pred_tag.pred_inx, predname,
seq1, seq2, predname, op_called, max_op_eq);
delete[] xseq1;
delete[] xseq2;
}
template
<class ForwardIterator1, class ForwardIterator2, class T, class PredTag>
void test_search (ForwardIterator1 it1, ForwardIterator2 it2,
const T* , PredTag pred_tag)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
static const char* const predname = "EqualityPredicate";
if (pred_tag.pred_inx) { // use predicate
rw_info (0, 0, 0,
"std::search (%s, %1$s, %s, %2$s, %s)",
it1name, it2name, predname);
}
else { // not use predicate
rw_info (0, 0, 0,
"std::search (%s, %1$s, %s, %2$s)",
it1name, it2name);
}
#define TEST(seq1, seq2, off) \
test_search (__LINE__, seq1, seq2, std::size_t (off), \
it1, it2, (T*)0, pred_tag)
//
// +--------------- sequence to search through
// | +---------- subsequence to search for
// | | +--- match found at offset
// v v v
TEST ("", "", 0);
TEST ("", "a", -1);
TEST ("", "ab", -1);
TEST ("", "abc", -1);
TEST ("a", "ab", -1);
TEST ("a", "a", 0);
TEST ("ab", "b", 1);
TEST ("ab", "bb", -1);
TEST ("abc", "a", 0);
TEST ("abc", "b", 1);
TEST ("abc", "c", 2);
TEST ("abc", "ac", -1);
TEST ("abc", "ab", 0);
TEST ("abc", "bc", 1);
TEST ("abc", "cd", -1);
TEST ("abc", "abc", 0);
TEST ("abcd", "ab", 0);
TEST ("abcd", "bc", 1);
TEST ("abcd", "cd", 2);
TEST ("abcd", "abc", 0);
TEST ("abcd", "bcd", 1);
TEST ("abcd", "bce", -1);
TEST ("abcde", "", 0);
TEST ("abcde", "a", 0);
TEST ("abcde", "b", 1);
TEST ("abcde", "c", 2);
TEST ("abcde", "d", 3);
TEST ("abcde", "e", 4);
TEST ("abcde", "ab", 0);
TEST ("abcde", "bc", 1);
TEST ("abcde", "cd", 2);
TEST ("abcde", "de", 3);
TEST ("abcde", "ef", -1);
TEST ("abcde", "abc", 0);
TEST ("abcde", "bcd", 1);
TEST ("abcde", "cde", 2);
TEST ("abcde", "def", -1);
TEST ("abcde", "abcd", 0);
TEST ("abcde", "bcde", 1);
TEST ("abcde", "cdef", -1);
TEST ("abcde", "abcde", 0);
TEST ("abcde", "bcdef", -1);
TEST ("abcabfg", "ab", 0);
TEST ("abcbcfg", "bc", 1);
TEST ("abcdecd", "cd", 2);
TEST ("abcdede", "de", 3);
}
/**************************************************************************/
// exercises std::search_n()
template <class ForwardIterator, class T, class Size, class PredTag>
void test_search_n (int line, const char *seq, Size cnt, const char val,
std::size_t off, ForwardIterator it,
const T* , PredTag pred_tag)
{
const char* const fname = "search_n";
static const char* const itname = type_name (it, (T*)0);
static const char* const szname = "Size";
static const char* const tname = "UserClass";
static const char* const predname =
pred_tag.pred_inx ? "BinaryPredicate" : "operator <()";
const std::size_t nseq = std::strlen (seq);
// construct a sequence of `nsrc' elements to pass to search_n
T* const xseq = T::from_char (seq, nseq);
// construct iterators pointing to the beginning and end
// of the source sequence
const ForwardIterator first =
make_iter (xseq, xseq, xseq + nseq, it);
const ForwardIterator last =
make_iter (xseq + nseq, xseq, xseq + nseq, it);
const ForwardIterator expected = _RWSTD_SIZE_MAX == off ?
last
: make_iter (xseq + off, xseq, xseq + off, it);
_RWSTD_UNUSED (expected);
T value;
value.data_.val_ = val;
T::n_total_op_eq_ = 0;
PredTag::Predicate::funcalls_ = 0;
typename PredTag::Predicate pred(0, 0);
const ForwardIterator result = pred_tag.pred_inx ?
std::search_n (first, last, cnt, value, pred)
: std::search_n (first, last, cnt, value);
_RWSTD_UNUSED (result);
// 25.1.9, p6:
// check the returned iterator
rw_assert (result.cur_ == expected.cur_, 0, line,
"std::%s<%s, %s, %s%{?}, %s%{;}> (\"%s\", ..., %d, '%c') "
"found subsequence at %td, expected at %{?}end%{:}%zu%{;}",
fname, itname, szname, tname, pred_tag.pred_inx, predname,
seq, int (cnt), val, result.cur_ - first.cur_,
_RWSTD_SIZE_MAX == off, off);
// 25.1.9, p7:
// Complexity: At most (last <20> first) * count
// applications of the corresponding predicate or operator.
// In real cases the complexity should be at most (last <20> first)
const std::size_t max_op_eq = nseq * cnt;
const std::size_t op_called = pred_tag.pred_inx ?
PredTag::Predicate::funcalls_
: T::n_total_op_eq_;
rw_assert (op_called <= max_op_eq, 0, line,
"std::%s<%s, %s, %s%{?}, %s%{;}> (\"%s\", ..., %d, '%c') "
"called %s %zu times, expected no more than %zu",
fname, itname, szname, tname, pred_tag.pred_inx, predname,
seq, int (cnt), val, predname, op_called, max_op_eq);
delete[] xseq;
}
template <class ForwardIterator, class T, class Size, class PredTag>
void test_search_n (ForwardIterator it, const T* ,
const Size* , PredTag pred_tag)
{
static const char* const itname = type_name (it, (T*)0);
static const char* const szname = "Size";
static const char* const tname = "UserClass";
static const char* const predname = "EqualityPredicate";
if (pred_tag.pred_inx) { // use predicate
rw_info (0, 0, 0,
"std::search_n (%s, %1$s, %s, const %s&, %s)",
itname, szname, tname, predname);
}
else { // not use predicate
rw_info (0, 0, 0,
"std::search_n (%s, %1$s, %s, const %s&)",
itname, szname, tname);
}
#undef TEST
#define TEST(seq, n, val, off) \
test_search_n (__LINE__, seq, Size(n, 0), val, std::size_t (off), \
it, (T*)0, pred_tag)
//
// +----------------- sequence to search through
// | +------------ number of occurrences
// | | +-------- element value to match
// | | | +--- match found at offset
// v v v v
TEST ("", 0, 'x', 0);
TEST ("", 1, 'x', -1);
TEST ("", 2, 'x', -1);
TEST ("", -1, 'x', -1);
TEST ("A", 0, 'B', 0);
TEST ("A", 0, 'A', 0);
TEST ("A", 1, 'B', -1);
TEST ("A", 1, 'A', 0);
TEST ("AB", 1, 'A', 0);
TEST ("AB", 2, 'A', -1);
TEST ("AB", 1, 'B', 1);
TEST ("AB", 2, 'B', -1);
TEST ("ABC", 0, 'A', 0);
TEST ("ABC", 0, 'B', 0);
TEST ("ABC", 0, 'C', 0);
TEST ("ABC", 0, 'D', 0);
TEST ("ABC", 1, 'A', 0);
TEST ("ABC", 1, 'B', 1);
TEST ("ABC", 1, 'C', 2);
TEST ("ABC", 1, 'D', -1);
TEST ("ABC", 2, 'A', -1);
TEST ("ABC", 2, 'B', -1);
TEST ("ABC", 2, 'C', -1);
TEST ("ABC", 2, 'D', -1);
TEST ("ABC", -1, 'A', -1);
TEST ("ABC", -2, 'B', -1);
TEST ("ABC", -3, 'C', -1);
TEST ("ABC", -4, 'D', -1);
TEST ("ABAD", 1, 'A', 0);
TEST ("ABCB", 1, 'B', 1);
TEST ("ABCC", 1, 'C', 2);
TEST ("ABAACAAAD", 2, 'A', 2);
TEST ("ABCBBDBBB", 2, 'B', 3);
TEST ("ABAACAADE", 3, 'A', -1);
TEST ("ABCBBDBBE", 3, 'B', -1);
TEST ("ABAACAAAD", 3, 'A', 5);
TEST ("ABCBBDBBB", 3, 'B', 6);
}
/**************************************************************************/
/* extern */ int rw_opt_no_search; // --no-search
/* extern */ int rw_opt_no_search_n; // --no-search_n
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/* extern */ int rw_opt_no_predicate; // --no-Predicate
template <class ForwardIterator, class T, class PredTag>
void test_search (ForwardIterator it, const T*, PredTag pred_tag)
{
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_search (it, FwdIter<T>(), (T*)0, pred_tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_search (it, BidirIter<T>(), (T*)0, pred_tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_search (it, RandomAccessIter<T>(), (T*)0, pred_tag);
}
}
/**************************************************************************/
template <class T, class PredTag>
void test_search (const T*, PredTag pred_tag)
{
rw_info (0, 0, 0,
"template <class %s, class %1$s%{?}, class %s%{;}> "
"std::search (%1$s, %1$s, %1$s, %1$s%{?}, %3$s%{;})",
"ForwardIterator", pred_tag.pred_inx, "BinaryPredicate",
pred_tag.pred_inx);
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_search (FwdIter<T>(), (T*)0, pred_tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_search (BidirIter<T>(), (T*)0, pred_tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_search (RandomAccessIter<T>(), (T*)0, pred_tag);
}
}
/**************************************************************************/
template <class T, class Size, class PredTag>
void test_search_n(const T* , Size* , PredTag pred_tag)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s%{?}, class %s%{;}> "
"std::search_n (%1$s, %1$s, %2$s, %s%{?}, %4$s%{;})",
"ForwardIterator", "Size", "T",
pred_tag.pred_inx, "BinaryPredicate", "const T&",
pred_tag.pred_inx);
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_search_n (FwdIter<T>(), (T*)0, (Size*)0, pred_tag);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_search_n (BidirIter<T>(), (T*)0, (Size*)0, pred_tag);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_search_n (RandomAccessIter<T>(), (T*)0, (Size*)0, pred_tag);
}
}
/**************************************************************************/
template <class T>
void test_search (const T*)
{
NonPredicateTag<T> non_predicate_tag = { false };
PredicateTag<T> predicate_tag = { true };
test_search ((T*)0, non_predicate_tag);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__, "std::search predicate test disabled");
}
else {
test_search ((T*)0, predicate_tag);
}
}
/**************************************************************************/
template <class T>
void test_search_n (const T*)
{
NonPredicateTag<T> non_predicate_tag = { false };
PredicateTag<T> predicate_tag = { true };
test_search_n ((T*)0, (Size<int>*)0, non_predicate_tag);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::search_n predicate test disabled");
}
else {
test_search_n ((T*)0, (Size<int>*)0, predicate_tag);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_search) {
rw_note (0, __FILE__, __LINE__, "std::search test disabled");
}
else {
test_search ((UserClass*)0);
}
if (rw_opt_no_search_n) {
rw_note (0, __FILE__, __LINE__, "std::search_n test disabled");
}
else {
test_search_n ((UserClass*)0);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.search",
0 /* no comment */, run_test,
"|-no-search# "
"|-no-search_n# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator# "
"|-no-Predicate",
&rw_opt_no_search,
&rw_opt_no_search_n,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,460 @@
/***************************************************************************
*
* 25.set.difference.cpp - test exercising lib.set.difference
*
* $Id: 25.set.difference.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for set_difference
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &x,
const UserClass &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
private:
void operator= (Less&); // not assignable
};
std::size_t Less::funcalls_;
/**************************************************************************/
// ordinary (non-template) base to minimize code bloat
struct SetDifferenceBase
{
virtual ~SetDifferenceBase() {}
const char* iter_names [3];
// pure virtual
virtual UserClass*
set_difference (const UserClass*, const UserClass*, const UserClass*,
const UserClass*, UserClass*, UserClass*,
const Less*) const = 0;
};
template <class InputIterator1, class InputIterator2, class OutputIterator>
struct SetDifference: SetDifferenceBase
{
SetDifference () {
iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
}
virtual UserClass*
set_difference (const UserClass *xsrc1, const UserClass *xsrc1_end,
const UserClass *xsrc2, const UserClass *xsrc2_end,
UserClass *xdst, UserClass *xdst_end,
const Less *ppred) const {
const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
const OutputIterator result (xdst, xdst, xdst_end);
const OutputIterator ret = ppred ?
std::set_difference (first1, last1, first2, last2, result, *ppred)
: std::set_difference (first1, last1, first2, last2, result);
// silence EDG eccp 3.7 and prior remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (ret);
return ret.cur_;
}
};
/**************************************************************************/
// exercises set_difference: 25.3.5.4
void test_set_difference (int line,
const char *src1,
std::size_t nsrc1,
const char *src2,
std::size_t nsrc2,
const char *res,
std::size_t ndst,
bool predicate,
const SetDifferenceBase &alg)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_difference";
const char* const funname = predicate ? "Less" : 0;
UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
true /* must be sorted */);
UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
true /* must be sorted */);
// assert that the sequences have been successfully created
RW_ASSERT (0 == nsrc1 || xsrc1);
RW_ASSERT (0 == nsrc2 || xsrc2);
UserClass* const xdst = new UserClass [ndst];
const int max1_id = nsrc1 > 0 ? xsrc1[nsrc1 - 1].id_ : -1;
UserClass* const xsrc1_end = xsrc1 + nsrc1;
UserClass* const xsrc2_end = xsrc2 + nsrc2;
UserClass* const xdst_end = xdst + ndst;
const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
const Less pred (0, 0);
const Less* const ppred = predicate ? &pred : 0;
UserClass* xdst_res = alg.set_difference (xsrc1, xsrc1_end,
xsrc2, xsrc2_end,
xdst, xdst_end, ppred);
// check the returned value
bool success = xdst_res == xdst_end;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"got res + %td, expected res + %zu",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, xdst_res - xdst, ndst);
// quit here to avoid the running out of the array boundaries
if (!success) {
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
return;
}
const std::size_t n_ops_lt = ppred ?
Less::funcalls_ : UserClass::n_total_op_lt_ - last_n_op_lt;
// verify the algorithm correctness
std::size_t i = 0;
std::size_t n1 = 0;
std::size_t n2 = 0;
for ( ; i < ndst; ++i) {
xdst[i].origin_ <= max1_id ? n1++ : n2++;
success = xdst[i].data_.val_ == res[i];
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\", expected \"%s\"",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst, res);
// verfiy that only elements from first sequence sequence were taken
success = n1 == ndst;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\" got %zu elements from first sequence and "
"%zu from second, expected %zu from first and 0 from second",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, int (ndst), -1, xdst, n1, n2, ndst);
// verify that the operation is stable : two equal elements
// should go in the same order
for (i = 1; i < ndst; i++) {
success = xdst[i - 1].origin_ < xdst[i].origin_;
if (!success)
break;
}
// to avoid errors in --trace mode
if (ndst > 1) {
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
" ==> \"%{X=*.*}\" not stable : elements %#c==%#c have "
"ids %d >= %d ",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst,
xdst[i - 1].data_.val_, xdst[i].data_.val_,
xdst[i - 1].origin_, xdst[i].origin_);
}
// verify the complexity
const std::size_t n_exp_ops =
nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"complexity: got %zu, expected no more than %zu",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
}
/**************************************************************************/
void test_set_difference (const SetDifferenceBase &alg,
bool predicate)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_difference";
const char* const funname = predicate ? "Less" : 0;
rw_info (0, 0, 0,
"%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
outname, fname, it1name, it2name, predicate, funname);
#define TEST(src1, src2, res) \
test_set_difference (__LINE__, src1, sizeof src1 - 1, \
src2, sizeof src2 - 1, res, sizeof res - 1, \
predicate, alg)
// +-------------------- first set
// | +----------- second set
// | | +-- difference
// | | |
// V V V
TEST ("a", "", "a");
TEST ("abcde", "", "abcde");
TEST ("", "a", "");
TEST ("", "abcde", "");
TEST ("a", "b", "a");
TEST ("b", "a", "b");
TEST ("aa", "aa", "");
TEST ("ab", "ab", "");
TEST ("aa", "ab", "a");
TEST ("aa", "bb", "aa");
TEST ("ab", "bb", "a");
TEST ("ac", "bb", "ac");
TEST ("ace", "bdf", "ace");
TEST ("acf", "bdf", "ac");
TEST ("ade", "bdf", "ae");
TEST ("bce", "bdf", "ce");
TEST ("aacee", "aacee", "");
TEST ("aacee", "aaace", "e");
TEST ("aacee", "aaaae", "ce");
TEST ("aacee", "aaaaa", "cee");
TEST ("aacee", "aaabd", "cee");
TEST ("aacee", "aabee", "c");
TEST ("aaaaa", "aaaaa", "");
TEST ("aaaaa", "aaaa", "a");
TEST ("aaaaa", "aaa", "aa");
TEST ("aaaaa", "aa", "aaa");
TEST ("aaaaa", "a", "aaaa");
TEST ("acegi", "bdfhj", "acegi");
TEST ("bdfhj", "acegi", "bdfhj");
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator1, class InputIterator2, class OutputIterator>
void gen_set_difference_test (const InputIterator1&,
const InputIterator2&,
const OutputIterator&,
bool predicate)
{
const SetDifference<InputIterator1, InputIterator2, OutputIterator> alg;
test_set_difference (alg, predicate);
}
/**************************************************************************/
template <class InputIterator1, class InputIterator2>
void gen_set_difference_test (const InputIterator1 &it1,
const InputIterator2 &it2,
bool predicate)
{
if (0 == rw_opt_no_output_iter)
gen_set_difference_test (
it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_difference_test (
it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_difference_test (
it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_difference_test (
it1, it2, RandomAccessIter<UserClass>(0, 0, 0), predicate);
}
template <class InputIterator1>
void gen_set_difference_test (const InputIterator1 &it1,
bool predicate)
{
if (0 == rw_opt_no_input_iter)
gen_set_difference_test (
it1, InputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_difference_test (
it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_difference_test (
it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_difference_test (
it1, ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
// generates a specialization of the set_union test for each of the required
// iterator categopries
void gen_set_difference_test (bool predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s%{?}, class %s%{;}> %3$s "
"set_difference (%1$s, %1$s, %2$s, %2$s, %3$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", "OutputIterator",
predicate, "Compare", predicate, "Compare");
if (rw_opt_no_output_iter)
rw_note (0, 0, 0, "OutputIterator test disabled");
if (rw_opt_no_input_iter)
rw_note (0, 0, 0, "InputIterator test disabled");
else
gen_set_difference_test (InputIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_fwd_iter)
rw_note (0, 0, 0, "ForwardIterator test disabled");
else
gen_set_difference_test (ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_set_difference_test (ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_set_difference_test (
ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_predicate)
rw_note (0, 0, 0, "predicate test disabled");
const int niters = rw_opt_no_predicate ? 1 : 2;
//////////////////////////////////////////////////////////////////
for (int i = 0; i != niters; ++i) {
gen_set_difference_test (1 == i);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.set.difference",
0 /* no comment */, run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,440 @@
/***************************************************************************
*
* 25. set.intersection.cpp - test exercising lib.set.intersection
*
* $Id: 25.set.intersection.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for set_intersection
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_intersection (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_intersection (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &x,
const UserClass &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
private:
void operator= (Less&); // not assignable
};
std::size_t Less::funcalls_;
/**************************************************************************/
struct SetIntersectionBase
{
virtual ~SetIntersectionBase() {}
const char* iter_names [3];
// pure virtual
virtual UserClass*
set_intersection (const UserClass*, const UserClass*, const UserClass*,
const UserClass*, UserClass*, UserClass*,
const Less*) const = 0;
};
template <class InputIterator1, class InputIterator2, class OutputIterator>
struct SetIntersection: SetIntersectionBase
{
SetIntersection () {
iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
}
virtual UserClass*
set_intersection (const UserClass *xsrc1, const UserClass *xsrc1_end,
const UserClass *xsrc2, const UserClass *xsrc2_end,
UserClass *xdst, UserClass *xdst_end,
const Less *ppred) const {
const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
const OutputIterator result (xdst, xdst, xdst_end);
const OutputIterator ret = ppred ?
std::set_intersection (first1, last1, first2,
last2, result, *ppred)
: std::set_intersection (first1, last1, first2,
last2, result);
// silence EDG eccp 3.7 and prior remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (ret);
return ret.cur_;
}
};
/**************************************************************************/
void test_set_intersection (int line,
const char *src1,
std::size_t nsrc1,
const char *src2,
std::size_t nsrc2,
const char *res,
std::size_t ndst,
bool predicate,
const SetIntersectionBase &alg)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_intersection";
const char* const funname = predicate ? "Less" : 0;
UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
true /* must be sorted */);
UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
true /* must be sorted */);
// assert that the sequences have been successfully created
RW_ASSERT (0 == nsrc1 || xsrc1);
RW_ASSERT (0 == nsrc2 || xsrc2);
UserClass* const xdst = new UserClass [ndst];
const int max1_id = nsrc1 > 0 ? xsrc1[nsrc1 - 1].id_ : -1;
UserClass* const xsrc1_end = xsrc1 + nsrc1;
UserClass* const xsrc2_end = xsrc2 + nsrc2;
UserClass* const xdst_end = xdst + ndst;
const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
const Less pred (0, 0);
const Less* const ppred = predicate ? &pred : 0;
const UserClass* const xdst_res =
alg.set_intersection (xsrc1, xsrc1_end, xsrc2,
xsrc2_end, xdst, xdst_end, ppred);
// check the returned value
bool success = xdst_res == xdst_end;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"got res + %td, expected res + %zu",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, xdst_res - xdst, ndst);
// quit here to avoid the running out of the array boundaries
if (!success) {
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
return;
}
const std::size_t n_ops_lt = ppred ?
Less::funcalls_ : UserClass::n_total_op_lt_ - last_n_op_lt;
// check the algorithm correctness
std::size_t i = 0;
std::size_t n1 = 0;
std::size_t n2 = 0;
for ( ; i < ndst; i++) {
xdst[i].origin_ <= max1_id ? n1++ : n2++;
success = xdst[i].data_.val_ == res[i];
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\", expected \"%s\"",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst, res);
// check that the operation is stable : for two equal elements
// one from the first sequence should be taken
success = n2 == 0;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\" got %zu elements from first sequence and "
"%zu from second, expected %zu from first and 0 from second",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, int (ndst), -1, xdst, n1, n2, ndst);
// check the complexity
const std::size_t n_exp_ops =
nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"complexity: got %zu, expected no more than %zu",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
}
/**************************************************************************/
void test_set_intersection (const SetIntersectionBase &alg,
bool predicate)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_intersection";
const char* const funname = predicate ? "Less" : 0;
rw_info (0, 0, 0,
"%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
outname, fname, it1name, it2name, predicate, funname);
#define TEST(src1, src2, res) \
test_set_intersection (__LINE__, src1, sizeof src1 - 1, \
src2, sizeof src2 - 1, \
res, sizeof res - 1, \
predicate, alg)
TEST ("a", "", "");
TEST ("abcde", "", "");
TEST ("", "a", "");
TEST ("", "abcde", "");
TEST ("a", "b", "");
TEST ("b", "a", "");
TEST ("aa", "aa", "aa");
TEST ("ab", "ab", "ab");
TEST ("aa", "ab", "a");
TEST ("ab", "bb", "b");
TEST ("aa", "bb", "");
TEST ("ac", "bb", "");
TEST ("ace", "bdf", "");
TEST ("acf", "bdf", "f");
TEST ("ade", "bdf", "d");
TEST ("bce", "bdf", "b");
TEST ("aacee", "aacee", "aacee");
TEST ("aacee", "aaace", "aace");
TEST ("aacee", "aaaae", "aae");
TEST ("aacee", "aaaaa", "aa");
TEST ("aaaae", "aacee", "aae");
TEST ("aaaaa", "aacee", "aa");
TEST ("aacee", "aaabd", "aa");
TEST ("aaabd", "aacee", "aa");
TEST ("aacee", "aabee", "aaee");
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator1, class InputIterator2, class OutputIterator>
void gen_set_intersection_test (const InputIterator1&,
const InputIterator2&,
const OutputIterator&,
bool predicate)
{
const SetIntersection<InputIterator1, InputIterator2, OutputIterator> alg;
test_set_intersection (alg, predicate);
}
/**************************************************************************/
template <class InputIterator1, class InputIterator2>
void gen_set_intersection_test (const InputIterator1 &it1,
const InputIterator2 &it2,
bool predicate)
{
if (0 == rw_opt_no_output_iter)
gen_set_intersection_test (
it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_intersection_test (
it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_intersection_test (
it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_intersection_test (
it1, it2, RandomAccessIter<UserClass>(0, 0, 0), predicate);
}
template <class InputIterator1>
void gen_set_intersection_test (const InputIterator1 &it1,
bool predicate)
{
if (0 == rw_opt_no_input_iter)
gen_set_intersection_test (
it1, InputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_intersection_test (
it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_intersection_test (
it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_intersection_test (
it1, ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
// generates a specialization of the set_intersection test for each of
// the required iterator categopries
static void
gen_set_intersection_test (bool predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s%{?}, class %s%{;}> %3$s "
"set_intersection(%1$s, %1$s, %2$s, %2$s, %3$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", "OutputIterator",
predicate, "Compare", predicate, "Compare");
if (rw_opt_no_output_iter)
rw_note (0, 0, 0, "OutputIterator test disabled");
if (rw_opt_no_input_iter)
rw_note (0, 0, 0, "InputIterator test disabled");
else
gen_set_intersection_test (InputIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_fwd_iter)
rw_note (0, 0, 0, "ForwardIterator test disabled");
else
gen_set_intersection_test (ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_set_intersection_test (ConstBidirIter<UserClass>(0, 0, 0),
predicate);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_set_intersection_test (
ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_predicate)
rw_note (0, 0, 0, "predicate test disabled");
const int niters = rw_opt_no_predicate ? 1 : 2;
//////////////////////////////////////////////////////////////////
for (int i = 0; i != niters; ++i) {
gen_set_intersection_test (1 == i);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.set.intersection",
0 /* no comment */,
run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,467 @@
/***************************************************************************
*
* 25.set.symmetric.difference.cpp - test for lib.set.symmetric.difference
*
* $Id: 25.set.sym.difference.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for set_symmetric_difference
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_symmetric_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_symmetric_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &x,
const UserClass &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
private:
void operator= (Less&); // not assignable
};
std::size_t Less::funcalls_;
/**************************************************************************/
struct SetSymDifferenceBase
{
virtual ~SetSymDifferenceBase() {}
const char* iter_names [3];
// ipure virtual
virtual UserClass*
set_sym_difference (const UserClass*, const UserClass*, const UserClass*,
const UserClass*, UserClass*, UserClass*,
const Less*) const = 0;
};
template <class InputIterator1, class InputIterator2, class OutputIterator>
struct SetSymDifference: SetSymDifferenceBase
{
SetSymDifference () {
iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
}
virtual ~SetSymDifference() {}
virtual UserClass*
set_sym_difference (const UserClass *xsrc1, const UserClass *xsrc1_end,
const UserClass *xsrc2, const UserClass *xsrc2_end,
UserClass *xdst, UserClass *xdst_end,
const Less *ppred) const {
const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
const OutputIterator result (xdst, xdst, xdst_end);
const OutputIterator ret = ppred ?
std::set_symmetric_difference (first1, last1, first2, last2,
result, *ppred)
: std::set_symmetric_difference (first1, last1, first2, last2,
result);
// silence EDG eccp 3.7 and prior remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (ret);
return ret.cur_;
}
};
/**************************************************************************/
// exercises set_difference: 25.3.5.5
void test_set_sym_difference (int line,
const char *src1,
std::size_t nsrc1,
const char *src2,
std::size_t nsrc2,
const char *res,
std::size_t ndst,
const std::size_t nf,
bool predicate,
const SetSymDifferenceBase &alg)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const algname = "set_symmetric_difference";
const char* const funname = predicate ? "Less" : 0;
UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
true /* must be sorted */);
UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
true /* must be sorted */);
UserClass* const xdst = new UserClass [ndst];
// source sequences must be sorted
RW_ASSERT (0 == nsrc1 || 0 != xsrc1);
RW_ASSERT (0 == nsrc2 || 0 != xsrc2);
const int max1_id = nsrc1 > 0 ? xsrc1 [nsrc1 - 1].id_ : -1;
UserClass* const xsrc1_end = xsrc1 + nsrc1;
UserClass* const xsrc2_end = xsrc2 + nsrc2;
UserClass* const xdst_end = xdst + ndst;
const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
const Less pred (0, 0);
const Less* const ppred = predicate ? &pred : 0;
UserClass* xdst_res = alg.set_sym_difference (xsrc1, xsrc1_end,
xsrc2, xsrc2_end,
xdst, xdst_end, ppred);
// check the returned value
bool success = xdst_res == xdst_end;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"got res + %td, expected res + %zu",
__LINE__, algname, it1name, it2name, outname, predicate,
funname, src1, src2, xdst_res - xdst, ndst);
//quit here to avoid the running out of the array boundaries
if (! success) {
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
return;
}
std::size_t n_ops_lt = ppred ?
Less::funcalls_ : UserClass::n_total_op_lt_ - last_n_op_lt;
// verify the algorithm correctness
std::size_t i = 0;
std::size_t n1 = 0;
std::size_t n2 = 0;
for ( ; i < ndst; i++) {
xdst [i].origin_ <= max1_id ? n1++ : n2++;
success = xdst [i].data_.val_ == res [i];
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\", expected \"%s\"",
__LINE__, algname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst, res);
// verfiy that only elements from first sequence sequence were taken
success = n1 == nf;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\" got %zu elements from first sequence and "
"%zu from second, expected %zu from first and %zu from second",
__LINE__, algname, it1name, it2name, outname, predicate,
funname, src1, src2,
int (ndst), -1, xdst, n1, n2, nf, ndst - nf);
// verify that the operation is stable: two equal elements
// should go in the same order
for (i = 1; i < ndst; i++) {
if (xdst [i - 1].data_.val_ == xdst [i].data_.val_) {
success = xdst [i - 1].origin_ < xdst [i].origin_;
if (!success)
break;
}
}
// to avoid errors in --trace mode
if (ndst > 1) {
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
" ==> \"%{X=*.*}\" not stable : elements %#c==%#c have "
"ids %d >= %d ",
__LINE__, algname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst,
xdst[i - 1].data_.val_, xdst[i].data_.val_,
xdst[i - 1].origin_, xdst[i].origin_);
}
// verify the complexity
std::size_t n_exp_ops = nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"complexity: got %zu, expected no more than %zu",
__LINE__, algname, it1name, it2name, outname, predicate,
funname, src1, src2, n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
}
/**************************************************************************/
void test_set_sym_difference (const SetSymDifferenceBase &alg,
bool predicate)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const algname = "set_symmetric_difference";
const char* const funname = predicate ? "Less" : 0;
rw_info (0, 0, 0,
"%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
outname, algname, it1name, it2name, predicate, funname);
#define TEST(src1, src2, res, nf) \
test_set_sym_difference (__LINE__, src1, sizeof src1 -1, \
src2, sizeof src2 - 1, \
res, sizeof res - 1, \
nf, predicate, alg)
// +------------------------------ first set
// | +--------------------- second set
// | | +------------ symmetric difference between them
// | | | +-- number of elements from the first
// | | | | sequence copied to the result
// V V V V
TEST ("a", "", "a", 1);
TEST ("abcde", "", "abcde", 5);
TEST ("", "a", "a", 0);
TEST ("", "abcde", "abcde", 0);
TEST ("a", "b", "ab", 1);
TEST ("b", "a", "ab", 1);
TEST ("aa", "aa", "", 0);
TEST ("ab", "ab", "", 0);
TEST ("aa", "ab", "ab", 1);
TEST ("aa", "bb", "aabb", 2);
TEST ("ab", "bb", "ab", 1);
TEST ("ac", "bb", "abbc", 2);
TEST ("ace", "bdf", "abcdef", 3);
TEST ("acf", "bdf", "abcd", 2);
TEST ("ade", "bdf", "abef", 2);
TEST ("bce", "bdf", "cdef", 2);
TEST ("aacee", "aacee", "", 0);
TEST ("aacee", "aaace", "ae", 1);
TEST ("aacee", "aaaae", "aace", 2);
TEST ("aacee", "aaaaa", "aaacee", 3);
TEST ("aacee", "aaabd", "abcdee", 3);
TEST ("aacee", "aabee", "bc", 1);
TEST ("aaaaa", "aaaaa", "", 0);
TEST ("aaaaa", "aaaa", "a", 1);
TEST ("aaaaa", "aaa", "aa", 2);
TEST ("aaaaa", "aa", "aaa", 3);
TEST ("aaaaa", "a", "aaaa", 4);
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator1, class InputIterator2, class OutputIterator>
void gen_set_sym_difference_test (const InputIterator1&,
const InputIterator2&,
const OutputIterator&,
bool predicate)
{
const SetSymDifference<
InputIterator1, InputIterator2, OutputIterator> alg;
test_set_sym_difference (alg, predicate);
}
/**************************************************************************/
template <class InputIterator1, class InputIterator2>
void gen_set_sym_difference_test (const InputIterator1 &it1,
const InputIterator2 &it2,
bool predicate)
{
if (0 == rw_opt_no_output_iter)
gen_set_sym_difference_test (
it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_sym_difference_test (
it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_sym_difference_test (
it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_sym_difference_test (
it1, it2, RandomAccessIter<UserClass>(0, 0, 0), predicate);
}
template <class InputIterator1>
void gen_set_sym_difference_test (const InputIterator1 &it1,
bool predicate)
{
if (0 == rw_opt_no_input_iter)
gen_set_sym_difference_test (
it1, InputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_sym_difference_test (
it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_sym_difference_test (
it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_sym_difference_test (
it1, ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
// generates a specialization of the set_union test for each of the required
// iterator categopries
void gen_set_sym_difference_test (bool predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s%{?}, class %s%{;}> %3$s "
"set_symmetric_difference (%1$s, %1$s, %2$s, %2$s, "
"%3$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", "OutputIterator",
predicate, "Compare", predicate, "Compare");
if (rw_opt_no_output_iter)
rw_note (0, 0, 0, "OutputIterator test disabled");
if (rw_opt_no_input_iter)
rw_note (0, 0, 0, "InputIterator test disabled");
else
gen_set_sym_difference_test (InputIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_fwd_iter)
rw_note (0, 0, 0, "ForwardIterator test disabled");
else
gen_set_sym_difference_test (ConstFwdIter<UserClass>(0, 0, 0),
predicate);
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_set_sym_difference_test (ConstBidirIter<UserClass>(0, 0, 0),
predicate);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_set_sym_difference_test (
ConstRandomAccessIter<UserClass>(0, 0, 0), predicate);
}
/**************************************************************************/
static int run_test (int, char*[])
{
if (rw_opt_no_predicate)
rw_note (0, 0, 0, "predicate test disabled");
const int niters = rw_opt_no_predicate ? 1 : 2;
//////////////////////////////////////////////////////////////////
for (int i = 0; i != niters; ++i) {
gen_set_sym_difference_test (1 == i);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.set.symmetric.difference",
0 /* no comment */, run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,432 @@
/***************************************************************************
*
* 25.set.union.cpp - test exercising 25.3.5.2 [lib.set.union]
*
* $Id: 25.set.union.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for set_union
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_union (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<lt_comp<assign<base<cpy_ctor> > > >
set_union (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
InputIter<lt_comp<assign<base<cpy_ctor> > > >,
OutputIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &x,
const UserClass &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
private:
void operator= (Less&); // not assignable
};
std::size_t Less::funcalls_;
/**************************************************************************/
// ordinary (non-template) base to minimize code bloat
struct SetUnionBase
{
virtual ~SetUnionBase() { /* no-op */ }
const char* iter_names [3];
// pure virtual, must be overridden
virtual UserClass*
set_union (const UserClass*, const UserClass*, const UserClass*,
const UserClass*, UserClass*, UserClass*,
const Less*) const = 0;
};
template <class InputIterator1, class InputIterator2, class OutputIterator>
struct SetUnion: SetUnionBase
{
SetUnion () {
iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
}
virtual UserClass*
set_union (const UserClass *xsrc1, const UserClass *xsrc1_end,
const UserClass *xsrc2, const UserClass *xsrc2_end,
UserClass *xdst, UserClass *xdst_end,
const Less *ppred) const {
const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
const OutputIterator result (xdst, xdst, xdst_end);
const OutputIterator ret = ppred ?
std::set_union (first1, last1, first2, last2, result, *ppred)
: std::set_union (first1, last1, first2, last2, result);
// silence EDG eccp 3.7 and prior remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (ret);
return ret.cur_;
}
};
/**************************************************************************/
void test_set_union (int line,
const char *src1,
std::size_t nsrc1,
const char *src2,
std::size_t nsrc2,
const char *res,
std::size_t ndst,
bool predicate,
const SetUnionBase &alg)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_union";
const char* const funname = predicate ? "Less" : 0;
UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
true /* must be sorted */);
UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
true /* must be sorted */);
// assert that the sequences have been successfully created
RW_ASSERT (0 == nsrc1 || xsrc1);
RW_ASSERT (0 == nsrc2 || xsrc2);
UserClass* const xdst = new UserClass [ndst];
const int max1_id = nsrc1 > 0 ? xsrc1 [nsrc1 - 1].id_ : -1;
UserClass* const xsrc1_end = xsrc1 + nsrc1;
UserClass* const xsrc2_end = xsrc2 + nsrc2;
UserClass* const xdst_end = xdst + ndst;
const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
const Less pred (0, 0);
const Less* const ppred = predicate ? &pred : 0;
const UserClass* const xdst_res =
alg.set_union (xsrc1, xsrc1_end, xsrc2, xsrc2_end,
xdst, xdst_end, ppred);
// check the returned value
bool success = xdst_res == xdst_end;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"got res + %td, expected res + %zu",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, xdst_res - xdst, ndst);
//quit here to avoid the running out of the array boundaries
if (! success) {
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
return;
}
const std::size_t n_ops_lt = ppred ?
Less::funcalls_ : UserClass::n_total_op_lt_ - last_n_op_lt;
// check the algorithm correctness
std::size_t i = 0;
std::size_t n1 = 0;
std::size_t n2 = 0;
for ( ; i < ndst; i++) {
xdst[i].origin_ <= max1_id ? n1++ : n2++;
success = xdst[i].data_.val_ == res[i];
if (!success)
break;
}
// to avoid errors in --trace mode
i = i < ndst ? i : ndst - 1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\", expected \"%s\"",
__LINE__, fname, it1name, it2name, outname, predicate,
funname, src1, src2, int (ndst), i, xdst, res);
// check that the operation is stable : for two equal elements
// one from the first sequence should be taken
success = n1 == nsrc1;
rw_assert (success, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
" ==> \"%{X=*.*}\" got %zu elements from first sequence and "
"%zu from second, expected %zu from first and %zu from second",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, int (ndst), -1, xdst, n1, n2, nsrc1, ndst - nsrc1);
// check the complexity
const std::size_t n_exp_ops =
nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
rw_assert (n_ops_lt <= n_exp_ops, 0, line,
"line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
"complexity: got %zu, expected no more than %zu",
__LINE__, fname, it1name, it2name, outname, predicate, funname,
src1, src2, n_ops_lt, n_exp_ops);
delete[] xsrc1;
delete[] xsrc2;
delete[] xdst;
}
/**************************************************************************/
void test_set_union (const SetUnionBase &alg,
bool predicate)
{
const char* const it1name = alg.iter_names [0];
const char* const it2name = alg.iter_names [1];
const char* const outname = alg.iter_names [2];
const char* const fname = "set_union";
const char* const funname = predicate ? "Less" : 0;
rw_info (0, 0, 0,
"%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
outname, fname, it1name, it2name, predicate, funname);
#define TEST(src1, src2, res) \
test_set_union (__LINE__, src1, sizeof src1 - 1, \
src2, sizeof src2 - 1, \
res, sizeof res - 1, \
predicate, alg)
TEST ("a", "", "a");
TEST ("abcde", "", "abcde");
TEST ("", "a", "a");
TEST ("", "abcde", "abcde");
TEST ("a", "b", "ab");
TEST ("b", "a", "ab");
TEST ("aa", "aa", "aa");
TEST ("ab", "ab", "ab");
TEST ("aa", "ab", "aab");
TEST ("aa", "bb", "aabb");
TEST ("ab", "bb", "abb");
TEST ("ac", "bb", "abbc");
TEST ("ace", "bdf", "abcdef");
TEST ("acf", "bdf", "abcdf");
TEST ("ade", "bdf", "abdef");
TEST ("bce", "bdf", "bcdef");
TEST ("abcde", "fghij", "abcdefghij");
TEST ("aacde", "ffhij", "aacdeffhij");
TEST ("abbde", "fggij", "abbdefggij");
TEST ("abcce", "fghhj", "abccefghhj");
TEST ("abcdd", "fghii", "abcddfghii");
TEST ("aacee", "aacee", "aacee");
TEST ("aacee", "aaace", "aaacee");
TEST ("aacee", "aaaae", "aaaacee");
TEST ("aacee", "aaaaa", "aaaaacee");
TEST ("aacee", "aaaab", "aaaabcee");
TEST ("aacee", "aaabd", "aaabcdee");
TEST ("aacee", "aabee", "aabcee");
}
/**************************************************************************/
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator1, class InputIterator2, class OutputIterator>
void gen_set_union_test (const InputIterator1&,
const InputIterator2&,
const OutputIterator&,
bool predicate)
{
const SetUnion<InputIterator1, InputIterator2, OutputIterator> alg;
test_set_union (alg, predicate);
}
/**************************************************************************/
template <class InputIterator1, class InputIterator2>
void gen_set_union_test (const InputIterator1 &it1,
const InputIterator2 &it2,
bool predicate)
{
if (0 == rw_opt_no_output_iter)
gen_set_union_test (it1, it2, OutputIter<UserClass>(0, 0, 0),
predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_union_test (it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_union_test (it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_union_test (it1, it2, RandomAccessIter<UserClass>(0, 0, 0),
predicate);
}
template <class InputIterator1>
void gen_set_union_test (const InputIterator1 &it1,
bool predicate)
{
if (0 == rw_opt_no_input_iter)
gen_set_union_test (it1, InputIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_fwd_iter)
gen_set_union_test (it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_bidir_iter)
gen_set_union_test (it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (0 == rw_opt_no_rnd_iter)
gen_set_union_test (it1, ConstRandomAccessIter<UserClass>(0, 0, 0),
predicate);
}
// generates a specialization of the set_union test for each of the required
// iterator categories
void gen_set_union_test (bool predicate)
{
rw_info (0, 0, 0,
"template <class %s, class %s, class %s%{?}, class %s%{;}> "
"%3$s set_union(%1$s, %1$s, %2$s, %2$s, %3$s%{?}, %s%{;})",
"InputIterator1", "InputIterator2", "OutputIterator",
predicate, "Compare", predicate, "Compare");
if (rw_opt_no_output_iter)
rw_note (0, 0, 0, "OutputIterator test disabled");
if (rw_opt_no_input_iter)
rw_note (0, 0, 0, "InputIterator test disabled");
else
gen_set_union_test (InputIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_fwd_iter)
rw_note (0, 0, 0, "ForwardIterator test disabled");
else
gen_set_union_test (ConstFwdIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_bidir_iter)
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
else
gen_set_union_test (ConstBidirIter<UserClass>(0, 0, 0), predicate);
if (rw_opt_no_rnd_iter)
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
else
gen_set_union_test (ConstRandomAccessIter<UserClass>(0, 0, 0),
predicate);
}
/**************************************************************************/
static int run_test (int, char*[])
{
if (rw_opt_no_predicate)
rw_note (0, 0, 0, "predicate test disabled");
const int niters = rw_opt_no_predicate ? 1 : 2;
//////////////////////////////////////////////////////////////////
for (int i = 0; i != niters; ++i) {
gen_set_union_test (1 == i);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.set.union",
0 /* no comment */,
run_test,
"|-no-predicate#"
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,418 @@
/***************************************************************************
*
* 25.sort.cpp - test exercising lib.sort and lib.stable.sort
*
* $Id: 25.sort.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for sort, stable_sort
#include <cstring> // for strlen, size_t
#include <cstddef> // for ptrdiff_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
template
void
stable_sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >);
template
void
stable_sort (RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
RandomAccessIter<lt_comp<assign<base<cpy_ctor> > > >,
binary_predicate<lt_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct Less
{
static std::size_t funcalls_;
// dummy arguments provided to prevent the class from being
// default constructible and implicit conversion from int
Less (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
++funcalls_;
return conv_to_bool::make (x.data_.val_ < y.data_.val_);
}
static const char* name () { return "Less"; }
private:
void operator= (Less&); // not assignable
};
template<class T> std::size_t Less<T>::funcalls_;
/**************************************************************************/
template <class T, class Predicate>
void test_sort (int line,
const char *src,
const std::size_t N,
const T*,
const Predicate *ppred,
bool stable,
bool alloc)
{
typedef RandomAccessIter<T> RandIter;
const RandIter it(0, 0, 0);
const char* const itname = "RandomAccessIterator";
const char* const fname = stable ? "stable_sort" : "sort";
const char* const funname = ppred ? Predicate::name() : "operator<()";
// generate random values for each default constructed T
T::gen_ = gen_rnd;
const std::size_t nsrc = src ? std::strlen (src) : N;
T* const xsrc = src ? T::from_char (src, nsrc) : new T[nsrc];
T* const xsrc_end = xsrc + nsrc;
RandIter first = make_iter (xsrc, xsrc, xsrc_end, it);
RandIter last = make_iter (xsrc_end, xsrc, xsrc_end, it);
const Predicate pred(0, 0);
std::size_t last_n_op_lt = T::n_total_op_lt_;
std::size_t last_n_op_cpy = T::n_total_op_assign_ + T::n_total_copy_ctor_;
_RWSTD_UNUSED (last_n_op_cpy);
if (stable) {
std::pair<UserClass*, std::ptrdiff_t> dummy;
if (alloc) {
dummy = std::_GET_TEMP_BUFFER (T, nsrc + 1);
rw_assert (0 != dummy.first, 0, 0,
"line %d: %s<%s%{?}, %s%{;}> (): "
"memory allocation failed for %zu elements",
__LINE__, fname, itname, ppred, funname, nsrc);
}
if (ppred)
std::stable_sort (first, last, pred);
else
std::stable_sort (first, last);
if (alloc && dummy.first)
std::return_temporary_buffer (dummy.first);
}
else {
if (ppred)
std::sort (first, last, pred);
else
std::sort (first, last);
}
// some tracing goes here
/*
if (! stable) {
// number of comparison operations
std::size_t ops = std::size_t (T::n_total_op_lt_ - last_n_op_lt);
// number of copy ctor and assignmen operator calls
std::size_t cpy =
std::size_t (T::n_total_op_assign_ + T::n_total_copy_ctor_)
- std::size_t (last_n_op_cpy);
// expected complexity (number opf comparisons)
std::size_t cmplx = (nsrc + 1) * ilog2 (nsrc + 2);
double x = double (ops) / cmplx;
// max and min T
static double x_max = 0.0;
static double x_min = 1.0;
if (x > x_max)
x_max = x;
if (nsrc > 16 && x < x_min)
x_min = x;
// complexity: UserClass * N * log (N),
// ideally with UserClass approaching 1
if (!(nsrc % 20)) {
rw_info (0, 0, 0,
"\n+------+------+------+------+------+------+------+\n"
"| N | COMP | COPY |N lg N| X | max X| min X|\n"
"+======+======+======+======+======+======+======+\n");
// # | comp | assign | exp. complexity | X | max X | min X
rw_info (0, 0, 0, "\n|%6d|%6d|%6d|%6d|%6.2f|%6.2f|%6.2f|\n",
nsrc + 1, ops, cpy, cmplx, x, x_max, x_min);
}
}
*/
// check that the array is sorted
bool success = is_sorted_lt (xsrc, xsrc_end);
if (src) {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\" not sorted",
__LINE__, fname, itname, ppred, funname, src,
int (nsrc), -1, xsrc);
}
else {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (%zu, ...): "
"not sorted",
__LINE__, fname, itname, ppred, funname, nsrc);
}
// verify 25.3.1.1, p2 and 25.3.1.2, p3
// the complexity of our implementation is no worse than
// 3.33 * N * log (N) (hence the magic 7 and 2)
const std::size_t n_ops =
ppred ? Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
const std::size_t exp_ops = 7 * nsrc * ::ilog2 (nsrc);
success = 2 * n_ops <= exp_ops;
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (): complexity for "
"length %zu is %zu, expected no more than %zu",
__LINE__, fname, itname, ppred, funname, nsrc,
n_ops, exp_ops / 2);
// verify 25.3.1.2 p2
if (stable) {
std::size_t j = 1;
for ( ; j < N; j++) {
if (xsrc[j - 1].data_.val_ == xsrc[j].data_.val_)
success = xsrc[j - 1].origin_ < xsrc[j].origin_;
if (!success)
break;
}
// to avoid errors in --trace mode
j = j < nsrc ? j : nsrc - 1;
if (src) {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (\"%s\", ...) ==> "
"\"%{X=*.*}\" relative order is broken at %zu: "
"got ids %zu and %zu for values %#c and %#c",
__LINE__, fname, itname, ppred, funname, src,
int (nsrc), -1, xsrc, j, xsrc[j - 1].origin_,
xsrc[j].origin_, xsrc[j - 1].data_.val_,
xsrc[j].data_.val_);
}
else {
rw_assert (success, 0, line,
"line %d: %s<%s%{?}, %s%{;}> (): relative order "
"is broken for %zu at %zu: got ids %zu and %zu "
"for values %d and %d",
__LINE__, fname, itname, ppred, funname,
nsrc, j, xsrc[j - 1].origin_, xsrc[j].origin_,
xsrc[j - 1].data_.val_, xsrc[j].data_.val_);
}
}
delete[] xsrc;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 256; // --nloops=#
/* extern */ int rw_opt_no_sort; // --no-sort
/* extern */ int rw_opt_no_stable_sort; // --no-stable_sort
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_complexity; // --no-complexity
/**************************************************************************/
template <class T, class Predicate>
void test_sort (const std::size_t N,
const T*,
const Predicate *ppred,
bool stable,
bool alloc)
{
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}> "
"void std::%{?}stable_%{;}sort (%1$s, %1$s%{?}, %3$s%{;})"
"%{?} with memory allocation%{;}",
"RandomAccessIterator", ppred, "StrictWeakComp",
stable, ppred, stable && alloc);
const char* const itname = "RandomAccessIterator";
const char* const fname = stable ? "stable_sort" : "sort";
const char* const funname = ppred ? Predicate::name() : "operator<()";
rw_info (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;})",
fname, itname, ppred, funname);
#define TEST(src) \
test_sort (__LINE__, src, 0, (T*)0, ppred, stable, alloc)
TEST ("a");
TEST ("ba");
TEST ("cba");
TEST ("dcba");
TEST ("edcba");
TEST ("fedcba");
TEST ("gfedcba");
TEST ("hgfedcba");
TEST ("ihgfedcba");
TEST ("jihgfedcba");
TEST ("ab");
TEST ("abc");
TEST ("abcd");
TEST ("abcde");
TEST ("abcdef");
TEST ("abcdefg");
TEST ("abcdefgh");
TEST ("abcdefghi");
TEST ("abcdefghij");
TEST ("aa");
TEST ("aabb");
TEST ("bbccaa");
TEST ("ddbbccaa");
TEST ("ddeebbccaa");
TEST ("aaaaaaaaaa");
TEST ("ababababab");
TEST ("bababababa");
#undef TEST
if (rw_opt_no_complexity) {
rw_note (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;}) complexity test disabled",
fname, itname, ppred, funname);
}
else {
rw_info (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;}): complexity test",
fname, itname, ppred, funname);
for (std::size_t i = 1; i < N; i++)
test_sort (__LINE__, 0, i, (T*)0, ppred, stable, alloc);
}
}
/**************************************************************************/
template <class T>
void test_sort (const std::size_t N,
const T*,
bool stable,
bool alloc)
{
test_sort (N, (T*)0, (Less<T>*)0, stable, alloc);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::%{?}stable_%{;}sort predicate test disabled",
stable);
}
else {
const Less<T> pred(0, 0);
test_sort (N, (T*)0, &pred, stable, alloc);
}
}
/**************************************************************************/
static int run_test (int, char*[])
{
const std::size_t N = std::size_t (rw_opt_nloops);
if (rw_opt_no_sort) {
rw_note (0, __FILE__, __LINE__, "std::sort test disabled");
}
else {
test_sort (N, (UserClass*)0, false, false);
}
if (rw_opt_no_stable_sort) {
rw_note (0, __FILE__, __LINE__, "std::stable_sort test disabled");
}
else {
test_sort (N, (UserClass*)0, true, false);
// test with memory reallocation
test_sort (N, (UserClass*)0, true, true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.sort",
0 /* no comment */,
run_test,
"|-nloops#0 " // must be non-negative
"|-no-sort# "
"|-no-stable_sort# "
"|-no-predicate",
&rw_opt_nloops,
&rw_opt_no_sort,
&rw_opt_no_stable_sort,
&rw_opt_no_predicate,
&rw_opt_no_complexity);
}

View File

@@ -0,0 +1,386 @@
/***************************************************************************
*
* 25.swap.cpp - test exercising 25.2.2 [lib.alg.swap]
*
* $Id: 25.swap.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for swap, swap_ranges, iter_swap
#include <cstring> // for size_t, strlen()
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
void
swap (assign<base<cpy_ctor> >&, assign<base<cpy_ctor> >&);
template
FwdIter<assign<base<cpy_ctor> > >
swap_ranges (FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >);
template
void
iter_swap (FwdIter<assign<base<cpy_ctor> > >,
FwdIter<assign<base<cpy_ctor> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T, class ForwardIterator1, class ForwardIterator2>
void test_iter_swap (int line,
const char* seq,
ForwardIterator1 /* dummy */,
ForwardIterator2 /* dummy */,
const T* /* dummy */,
bool it_swap,
const char* it1name,
const char* it2name,
const char* fname)
{
// generate sequential values for each default constructed T
const std::size_t nseq = std::strlen (seq);
// construct a sequence of `nseq' elements to pass to swap
T* const tseq = T::from_char (seq, nseq + 1);
int a_val, b_val;
bool success = true;
std::size_t i = 1;
for ( ; i < nseq; ++i) {
const ForwardIterator1 it1 =
make_iter (tseq, tseq, tseq + nseq, it1);
const ForwardIterator2 it2 =
make_iter (tseq + i, tseq, tseq + nseq, it2);
a_val = (*it1).data_.val_;
b_val = (*it2).data_.val_;
it_swap ? std::iter_swap (it1, it2) : std::swap(*it1, *it2);
// verify 25.2.2, p2, p7
success = a_val == (*it2).data_.val_ && b_val == (*it1).data_.val_;
if (!success)
break;
}
rw_assert (success, 0, line,
"%s<%s%{?}, %s%{;}>(%#c, %#c): got: { %#c, %#c } "
"expected: { %5$#c, %4$#c } at step %zu",
fname, it1name, it_swap, it2name, a_val, b_val,
tseq->data_.val_, (tseq + i)->data_.val_, i);
delete[] tseq;
}
template <class T, class ForwardIterator1, class ForwardIterator2>
void test_iter_swap (ForwardIterator1 it1, ForwardIterator2 it2,
const T*, bool it_swap)
{
const char* const it1name = it_swap ? type_name (it1, (T*)0) : "UserClass";
const char* const it2name = it_swap ? type_name (it2, (T*)0) : "UserClass";
const char* const fname = it_swap ? "iter_swap" : "swap";
rw_info (0, 0, 0, "std::%s (%s, %s)", fname, it1name, it2name);
#undef TEST
#define TEST(seq) \
test_iter_swap (__LINE__, seq, it1, it2, (T*)0, it_swap, \
it1name, it2name, fname)
TEST("ab");
TEST("abc");
TEST("abcd");
TEST("abcde");
TEST("abcdef");
TEST("abcdefg");
TEST("abcdefgh");
TEST("abcdefghi");
TEST("abcdefghij");
TEST("abcdefghijk");
}
/**************************************************************************/
template <class T, class ForwardIterator1, class ForwardIterator2>
void test_swap_ranges (int line,
const char* seq1,
const char* seq2,
ForwardIterator1 it1,
ForwardIterator2 it2,
const T* /* dummy */,
const char* it1name,
const char* it2name)
{
const std::size_t nseq = std::strlen (seq1);
// construct a sequence of `nseq' elements to pass to swap_ranges
T* const tseq1 = T::from_char (seq1, nseq + 1);
T* const tseq2 = T::from_char (seq2, nseq + 1);
const ForwardIterator1 first1 =
make_iter (tseq1, tseq1, tseq1 + nseq, it1);
const ForwardIterator1 last1 =
make_iter (tseq1 + nseq, tseq1, tseq1 + nseq, it1);
const ForwardIterator2 first2 =
make_iter (tseq2, tseq2, tseq2 + nseq, it2);
const ForwardIterator2 last2 =
make_iter (tseq2 + nseq, tseq2, tseq2 + nseq, it2);
// silence bogus EDG eccp remark #550-D: variable was set
// but never used
_RWSTD_UNUSED (last2);
T a, b;
std::size_t last_n_op_assign = T::n_total_op_assign_;
std::swap (a, b);
std::size_t assigns_per_swap = T::n_total_op_assign_ - last_n_op_assign;
last_n_op_assign = T::n_total_op_assign_;
// exercise 25.2.3 - std::swap_ranges()
const ForwardIterator2 res = std::swap_ranges(first1, last1, first2);
// silence bogus EDG eccp remark #550-D: variable was set
// but never used
_RWSTD_UNUSED (res);
// check the returned value, 25.2.2 p5
bool success = res.cur_ == last2.cur_;
rw_assert (success, 0, line,
"swap_ranges<%s, %s>(\"%s\", \"%s\") == first + %td, "
"got first + %td",
it1name, it2name, seq1, seq2, res.cur_ - tseq2,
last2.cur_ - tseq2);
// check that the sequences were swapped, 25.2.2 p4
std::size_t i = 0;
for ( ; i < nseq; ++i) {
success = (tseq1 + i)->data_.val_ == seq2[i]
&& (tseq2 + i)->data_.val_ == seq1[i];
if (!success)
break;
}
rw_assert (success, 0, line,
"swap_ranges<%s, %s>(\"%s\", \"%s\") mismatch at pos %zu "
"got { %#c, %#c }, expected { %#c, %#c }",
it1name, it2name, seq1, seq2, i, (tseq1 + i)->data_.val_,
(tseq2 + i)->data_.val_, seq2[i], seq1[i]);
// check the complexity, 25.2.2 p6
std::size_t swaps_per_swap_ranges =
(T::n_total_op_assign_ - last_n_op_assign) / assigns_per_swap;
rw_assert (swaps_per_swap_ranges == nseq, 0, line,
"swap_ranges<%s, %s>(\"%s\", \"%s\") complexity: "
"%zu, expected %zu swaps",
it1name, it2name, seq1, seq2, swaps_per_swap_ranges, nseq);
delete[] tseq1;
delete[] tseq2;
}
/**************************************************************************/
template <class T, class ForwardIterator1, class ForwardIterator2>
void test_swap_ranges (ForwardIterator1 it1,
ForwardIterator2 it2,
const T* /* dummy */)
{
static const char* const it1name = type_name (it1, (T*)0);
static const char* const it2name = type_name (it2, (T*)0);
rw_info (0, 0, 0,
"std::swap_ranges (%s, %1$s, %s)", it1name, it2name);
#undef TEST
#define TEST(seq1, seq2) \
test_swap_ranges (__LINE__, seq1, seq2, it1, it2, (T*)0, \
it1name, it2name)
TEST("", "");
TEST("a", "z");
TEST("ab", "zy");
TEST("abc", "zyx");
TEST("abcd", "zyxw");
TEST("abcde", "zyxwv");
TEST("abcdef", "zyxwvu");
TEST("abcdefg", "zyxwvut");
TEST("abcdefgh", "zyxwvuts");
TEST("abcdefghi", "zyxwvutsr");
TEST("abcdefghij", "zyxwvutsrq");
TEST("abcdefghijk", "zyxwvutsrqp");
TEST("abcdefghijkl", "zyxwvutsrqpo");
TEST("abcdefghijklm", "zyxwvutsrqpon");
}
/**************************************************************************/
/* extern */ int rw_opt_no_swap; // --no-swap
/* extern */ int rw_opt_no_swap_ranges; // --no-swap_ranges
/* extern */ int rw_opt_no_iter_swap; // --no-iter_swap
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T, class ForwardIterator1>
void test_swap (ForwardIterator1 it1, const T*, bool test_ranges)
{
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
if (test_ranges)
test_swap_ranges (it1, FwdIter<T>(), (T*)0);
else
test_iter_swap (it1, FwdIter<T>(), (T*)0, true);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
if (test_ranges)
test_swap_ranges (it1, BidirIter<T>(), (T*)0);
else
test_iter_swap (it1, BidirIter<T>(), (T*)0, true);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
if (test_ranges)
test_swap_ranges (it1, RandomAccessIter<T>(), (T*)0);
else
test_iter_swap (it1, RandomAccessIter<T>(), (T*)0, true);
}
}
/**************************************************************************/
template <class T>
void test_swap (const T*, bool test_ranges)
{
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_swap (FwdIter<T>(), (T*)0, test_ranges);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_swap (BidirIter<T>(), (T*)0, test_ranges);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_swap (RandomAccessIter<T>(), (T*)0, test_ranges);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_swap) {
rw_note (0, __FILE__, __LINE__, "std::swap test disabled");
}
else {
rw_info (0, 0, 0, "template <class T> void swap (T&, T&)");
test_iter_swap (FwdIter<UserClass>(), FwdIter<UserClass>(),
(UserClass*)0, false);
}
if (rw_opt_no_swap_ranges) {
rw_note (0, __FILE__, __LINE__, "std::swap_ranges test disabled");
}
else {
rw_info (0, 0, 0,
"template <class %s, class %s> %2$s "
"swap_ranges (%1$s, %1$s, %2$s)",
"ForwardIterator1", "ForwardIterator2");
test_swap ((UserClass*)0, true);
}
if (rw_opt_no_iter_swap) {
rw_note (0, __FILE__, __LINE__, "std::iter_swap test disabled");
}
else {
rw_info (0, 0, 0,
"template <class %s, class %s> void iter_swap (%1$s, %2$s)",
"ForwardIterator1", "ForwardIterator2");
test_swap ((UserClass*)0, false);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.swap",
0 /* no comment */, run_test,
"|-no-swap# "
"|-no-swap_ranges# "
"|-no-iter_swap# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator",
&rw_opt_no_swap,
&rw_opt_no_swap_ranges,
&rw_opt_no_iter_swap,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,504 @@
/***************************************************************************
*
* 25.transform.cpp - test exercising 25.2.3 [lib.alg.transform]
*
* $Id: 25.transform.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <algorithm> // for transform
#include <cstddef> // for size_t
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
_RWSTD_NAMESPACE (std) {
// disable explicit instantiation for compilers (like MSVC)
// that can't handle it
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
template
OutputIter<assign<base<> > >
transform (InputIter<assign<base<> > >,
InputIter<assign<base<> > >,
OutputIter<assign<base<> > >,
func<assign<base<> > >);
template
OutputIter<assign<base<> > >
transform (InputIter<assign<base<> > >,
InputIter<assign<base<> > >,
InputIter<assign<base<> > >,
OutputIter<assign<base<> > >,
binary_func<assign<base<> > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
template <class T>
struct incT
{
// not a binary function
enum { binary = 0 };
// function name
static const char* name () { return "unary_function"; }
// dummy arguments to prevent the class from being default
// constructible or construtible by conversion from an int
incT (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// non-const in order to detect unwarranted assumptions
// in the algorithm(s)
T operator() (const T &x) /* non-const */ {
++funcalls_;
T y (x);
y.data_.val_ += 1;
return y;
}
static std::size_t funcalls_;
};
template <class T>
struct plusT
{
// binary function
enum { binary = 1 };
// function name
static const char* name () { return "binary_function"; }
// dummy arguments to prevent the class from being default
// constructible or construtible by conversion from an int
plusT (int, int) {
funcalls_ = 0;
}
// non-const in order to detect unwarranted assumptions
// in the algorithm(s)
T operator() (const T &a, const T &b) /* non-const */ {
++funcalls_;
T x (a);
x.data_.val_ = a.data_.val_ + b.data_.val_;
return x;
}
static std::size_t funcalls_;
};
template <class T> std::size_t incT<T>::funcalls_;
template <class T> std::size_t plusT<T>::funcalls_;
/**************************************************************************/
/* extern */ int rw_opt_nloops = 32; // --nloops=#
/* extern */ int rw_opt_no_unary_function; // --no-unary_function
/* extern */ int rw_opt_no_binary_function; // --no-binary_function
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
/**************************************************************************/
template <class InputIterator, class Unused, class OutputIterator>
OutputIterator
invoke_transform (InputIterator first, InputIterator last,
Unused /* for compatibility with the overload below */,
OutputIterator dest, incT<UserClass> fun)
{
return std::transform (first, last, dest, fun);
}
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
invoke_transform (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2,
OutputIterator dest, plusT<UserClass> fun)
{
return std::transform (first1, last1, first2, dest, fun);
}
template <class T, class InputIterator1, class InputIterator2,
class OutputIterator, class Function>
void test_transform (const T* ptr,
const InputIterator1 &it1,
const InputIterator2 &it2,
const OutputIterator &out,
const Function*,
int same_seq)
{
static const char* const it1name = type_name (it1, ptr);
static const char* const it2name = type_name (it2, ptr);
static const char* const outname = type_name (out, ptr);
static const char* const algname = "transform";
static const char* const funname = Function::name ();
static const bool binary = Function::binary;
const std::size_t nloops = std::size_t (rw_opt_nloops);
rw_info (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, %s%d == %s%{;}",
algname, it1name, binary, it2name, outname, funname,
same_seq, "first", same_seq, "dest");
// generate sequential values for each default constructed T
T::gen_ = gen_seq;
// make sure buf{1,2}[0] is dereferenceable even when (nloops == 0)
T* const buf1 = new T [nloops + 1];
T* const buf2 = new T [nloops + 1];
T* const buf3 = same_seq ? (same_seq == 1 ? buf1 : buf2) : new T [nloops];
const int start1_val =
same_seq == 2 ? buf2 [0].data_.val_ : buf1 [0].data_.val_;
const int start2_val =
same_seq == 2 ? buf1 [0].data_.val_ : buf2 [0].data_.val_;
for (std::size_t i = 0; i < nloops; ++i) {
T* const buf1_end = buf1 + i;
const T* const buf2_end = buf2 + i;
const T* const buf3_end = buf3 + i;
const InputIterator1 first1 = make_iter (buf1, buf1, buf1_end, it1);
const InputIterator1 last1 = make_iter (buf1_end, buf1, buf1_end, it1);
const InputIterator2 first2 = make_iter (buf2, buf2, buf2_end, it2);
const OutputIterator dest = make_iter (buf3, buf3, buf3_end, out);
const Function fun (0, 0); // dummy arguments
// invoke the overload of std::transform() appropriate
// for this Function
const OutputIterator result =
invoke_transform (first1, last1, first2, dest, fun);
// check the returned iterator
bool success = result.cur_ == buf3_end;
rw_assert (success, 0, __LINE__,
"%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
"%s%d == %s%{;} : return val: "
"dest + %td, expected dest + %zu",
i, algname, it1name, binary, it2name, outname, funname,
same_seq, "first", same_seq, "dest",
result.cur_ - buf3, i);
if (!success)
break;
// check the transformation results
int exp_val = 0;
std::size_t j = 0;
for ( ; j < i; j++) {
if (0 == same_seq) {
exp_val = binary ?
start1_val + int (j) + start2_val + int (j)
: start1_val + int (j) + 1;
}
else {
exp_val = binary ?
start1_val + int (j)
+ (start2_val + int (j)) * int (i - j)
: start1_val + int (i);
}
success = buf3 [j].data_.val_ == exp_val;
if (!success)
break;
}
rw_assert (success, 0, __LINE__,
"%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
"%s%d == %s%{;} : error: incorrect value %d, "
"expected %d, position %zu",
i, algname, it1name, binary, it2name, outname, funname,
same_seq, "first", same_seq, "dest",
buf3 [j].data_.val_, exp_val, j + 1);
if (!success)
break;
// check compexity, 25.2.3 p4
rw_assert (Function::funcalls_ == i, 0, __LINE__,
"%zu. %s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, "
"%s%d == %s%{;} : complexity : %zu "
"applications of %5$s, expected %zu",
i, algname, it1name, binary, it2name, outname, funname,
same_seq, "first", same_seq, "dest",
Function::funcalls_, i);
}
delete[] buf1;
delete[] buf2;
if (0 == same_seq)
delete[] buf3;
}
/**************************************************************************/
template <class T, class InputIterator1, class InputIterator2,
class OutputIterator, class Function>
void gen_test (const T* ptr,
const InputIterator1 &it1,
const InputIterator2 &it2,
const OutputIterator &out,
const Function* pfun,
int tag1,
int tag2,
int tag3,
int same_seq)
{
const InputIter<UserClass> input_iter (0, 0, 0);
const OutputIter<T> output_iter (0, 0, 0);
const FwdIter<T> fwd_iter (0, 0, 0);
const BidirIter<T> bidir_iter (0, 0, 0);
const RandomAccessIter<UserClass> rand_iter (0, 0, 0);
// tag1, tag2 and tag3 indicates that an iterator needs to be generated
// at the corresponding position by a recursive call to gen_test
// and other positions there the iterator will be used
// for all tags:
// 0 means that no iterator is needed here
// (maybe it was already generated or just not needed)
// 1 means that the iterator is needed at this position
// (first for tag1, second for tag2, etc)
// 2 means that the iterator is needed at this position and the
// same type of iterator should be used at third position
//////////////////////////////////////////////////////////////////
if (rw_opt_no_input_iter) {
if (1 == tag1 || 0 == tag1 && 1 == tag2)
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
if (1 == tag1) {
gen_test (ptr, input_iter, it2, out,
pfun, 0, tag2, tag3, same_seq);
}
else if (0 == tag1 && 1 == tag2) {
gen_test (ptr, it1, input_iter, out,
pfun, tag1, 0, tag3, same_seq);
}
}
//////////////////////////////////////////////////////////////////
if (rw_opt_no_fwd_iter) {
if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
if (1 == tag1) {
gen_test (ptr, fwd_iter, it2, out,
pfun, 0, tag2, tag3, same_seq);
}
else if (2 == tag1) {
gen_test (ptr, fwd_iter, it2, fwd_iter,
pfun, 0, tag2, 0, same_seq);
}
else if (0 == tag1 && 1 == tag2) {
gen_test (ptr, it1, fwd_iter, out,
pfun, tag1, 0, tag3, same_seq);
}
else if (0 == tag1 && 2 == tag2) {
gen_test (ptr, it1, fwd_iter, fwd_iter,
pfun, tag1, 0, 0, same_seq);
}
else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
gen_test (ptr, it1, it2, fwd_iter,
pfun, tag1, tag2, 0, same_seq);
}
}
//////////////////////////////////////////////////////////////////
if (rw_opt_no_bidir_iter) {
if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
if (1 == tag1) {
gen_test (ptr, bidir_iter, it2, out,
pfun, 0, tag2, tag3, same_seq);
}
else if (2 == tag1) {
gen_test (ptr, bidir_iter, it2, bidir_iter,
pfun, 0, tag2, 0, same_seq);
}
else if (0 == tag1 && 1 == tag2) {
gen_test (ptr, it1, bidir_iter, out,
pfun, tag1, 0, tag3, same_seq);
}
else if (0 == tag1 && 2 == tag2) {
gen_test (ptr, it1, bidir_iter, bidir_iter,
pfun, tag1, 0, 0, same_seq);
}
else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
gen_test (ptr, it1, it2, bidir_iter,
pfun, tag1, tag2, 0, same_seq);
}
}
//////////////////////////////////////////////////////////////////
if (rw_opt_no_rnd_iter) {
if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3)
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
if (1 == tag1) {
gen_test (ptr, rand_iter, it2, out,
pfun, 0, tag2, tag3, same_seq);
}
else if (2 == tag1) {
gen_test (ptr, rand_iter, it2, rand_iter,
pfun, 0, tag2, 0, same_seq);
}
else if (0 == tag1 && 1 == tag2) {
gen_test (ptr, it1, rand_iter, out,
pfun, tag1, 0, tag3, same_seq);
}
else if (0 == tag1 && 2 == tag2) {
gen_test (ptr, it1, rand_iter, rand_iter,
pfun, tag1, 0, 0, same_seq);
}
else if (0 == tag1 && 0 == tag2 && 1 == tag3) {
gen_test (ptr, it1, it2, rand_iter,
pfun, tag1, tag2, 0, same_seq);
}
}
//////////////////////////////////////////////////////////////////
if (rw_opt_no_output_iter) {
if (0 == tag1 && 0 == tag2 && 1 == tag3)
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
if (0 == tag1 && 0 == tag2 && 1 == tag3) {
gen_test (ptr, it1, it2, output_iter,
pfun, tag1, tag2, 0, same_seq);
}
}
if (0 == tag1 && 0 == tag2 && 0 == tag3) {
test_transform (ptr, it1, it2, out, pfun, same_seq);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
const InputIter<UserClass> input_iter (0, 0, 0);
const RandomAccessIter<UserClass> rand_iter;
const UserClass* const ptr = 0;
// test transform with a unary function
// according to 25.2.3 p5 'result may be equal to first'
// so it is neccessary to test this case separately
if (rw_opt_no_unary_function) {
rw_note (0, __FILE__, __LINE__,
"std::transform unary function test disabled");
}
else {
const incT<UserClass>* const pfun = 0;
gen_test (ptr, input_iter, rand_iter, rand_iter,
pfun, 1, 0, 1, 0 /* result distinct from first */);
// test 25.2.3 p5 - result is equal to first
// set tag1 = 2 and tag3 = 0 to test all iterators at the first
// position and avoid generating iterators at the third pos
gen_test (ptr, input_iter, rand_iter, rand_iter,
pfun, 2, 0, 0, 1 /* result same as first */);
}
// test transform with a binary function
// according to 25.2.3 p5 'result may be equal to first1 or first2'
// so it is neccessary to test these cases separately
if (rw_opt_no_binary_function) {
rw_note (0, __FILE__, __LINE__,
"std::transform binary function test disabled");
}
else {
const plusT<UserClass>* const pfun = 0;
gen_test (ptr, input_iter, rand_iter, rand_iter,
pfun, 1, 1, 1, 0 /* result distinct from first{1,2} */);
// test 25.2.3 p5 - result is equal to first2
// set tag2 = 2 and tag3 = 0 to test all iterators at the second
// position and avoid generating iterators at the third pos
gen_test (ptr, input_iter, rand_iter, rand_iter,
pfun, 1, 2, 0, 2 /* result same as first2 */);
// test 25.2.3 p5 - result is equal to first1
// set tag1 = 2 and tag3 = 0 to test all iterators at the first
// position and avoid generating iterators at the third pos
// set same_seq to 1 to indicate that first1 and dest should be
// the same iterators
gen_test (ptr, input_iter, rand_iter, rand_iter,
pfun, 2, 1, 0, 1 /* result same as first1 */);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.transform",
0 /* no comment */, run_test,
"|-nloops#0 " // must be non-negative
"|-no-unary_function# "
"|-no-binary_function# "
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator",
&rw_opt_nloops,
&rw_opt_no_unary_function,
&rw_opt_no_binary_function,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}

View File

@@ -0,0 +1,408 @@
/***************************************************************************
*
* unique.cpp - test exercising 25.2.8 [lib.alg.unique]
*
* $Id: 25.unique.cpp 510071 2007-02-21 15:58:53Z 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 2000-2006 Rogue Wave Software.
*
**************************************************************************/
#include <algorithm> // for unique, unique_copy
#include <cstring> // for strlen
#include <alg_test.h> // for BinaryPredicate
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test()
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
// also exercise LWG issue 241:
// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241
template
FwdIter<eq_comp<assign<base<> > > >
unique (FwdIter<eq_comp<assign<base<> > > >,
FwdIter<eq_comp<assign<base<> > > >);
template
FwdIter<eq_comp<assign<base<> > > >
unique (FwdIter<eq_comp<assign<base<> > > >,
FwdIter<eq_comp<assign<base<> > > >,
binary_predicate<eq_comp<assign<base<> > > >);
template
OutputIter<eq_comp<assign<base<cpy_ctor> > > >
unique_copy (InputIter<eq_comp<assign<base<cpy_ctor> > > >,
InputIter<eq_comp<assign<base<cpy_ctor> > > >,
OutputIter<eq_comp<assign<base<cpy_ctor> > > >);
template
OutputIter<eq_comp<assign<base<cpy_ctor> > > >
unique_copy (InputIter<eq_comp<assign<base<cpy_ctor> > > >,
InputIter<eq_comp<assign<base<cpy_ctor> > > >,
OutputIter<eq_comp<assign<base<cpy_ctor> > > >,
binary_predicate<eq_comp<assign<base<cpy_ctor> > > >);
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
} // namespace std
/**************************************************************************/
// exercises std::unique and std::unique_copy()
template <class FwdIterator, class FwdCopyIterator,
class OutIterator, class T, class Predicate>
void test_unique (int line,
const char *src,
const char *dst,
const FwdIterator &it,
const FwdCopyIterator &itc,
const OutIterator &out,
const T*,
const Predicate *ppred,
bool use_copy)
{
const char* const outname = type_name (out, (T*)0);
const char* const itname =
use_copy ? type_name (itc, (T*)0) : type_name (it, (T*)0);
const char* const fname =
use_copy ? "unique_copy" : "unique";
const char* const funname =
ppred ? "BinaryPredicate" : "operator==()";
const std::size_t nsrc = std::strlen (src);
const std::size_t ndst = std::strlen (dst);
T* const xsrc = T::from_char (src, nsrc);
T* xdst = use_copy ? T::from_char (dst, ndst) : xsrc;
T* const xsrc_end = xsrc + nsrc;
T* const xdst_end = xdst + ndst;
const FwdIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
const FwdIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
const FwdCopyIterator first_c = make_iter (xsrc, xsrc, xsrc_end, itc);
const FwdCopyIterator last_c = make_iter (xsrc_end, xsrc, xsrc_end, itc);
const OutIterator result = make_iter (xdst, xdst, xdst_end, out);
// compute the actual number of invocations of operator==() or predicate
std::size_t n_total_ops =
ppred ? Predicate::n_total_op_fcall_ : T::n_total_op_eq_;
OutIterator res_c (0, 0, 0);
FwdIterator res (0, 0, 0);
if (use_copy)
res_c = ppred ?
std::unique_copy (first_c, last_c, result, *ppred)
: std::unique_copy (first_c, last_c, result);
else
res = ppred ?
std::unique (first, last, *ppred)
: std::unique (first, last);
const T* const f_cur = use_copy ? result.cur_ : first.cur_;
const T* const r_cur = use_copy ? res_c.cur_ : res.cur_;
bool success = r_cur == f_cur + ndst;
rw_assert (success, 0, line,
"line %d: std::%s <%s%{?}, %s%{;}%{?}, %s%{;}>(\"%s\", ...) "
"== (res + %zu), got (res + %td)",
__LINE__, fname, itname, use_copy, outname, 0 != ppred,
funname, src, ndst, r_cur - f_cur);
// verify that the copied sequence matches the expected range
const T* const mismatch = T::mismatch (xdst, dst, ndst);
rw_assert (0 == mismatch, 0, line,
"line %d: std::%s <%s%{?}, %s%{;}%{?}, %s%{;}>(\"%s\", ...) "
"==> \"%s\", got \"%{X=*.@}\"",
__LINE__, fname, itname, use_copy, outname, 0 != ppred,
funname, src, dst, int (ndst), mismatch, xdst);
if (ppred)
n_total_ops = ppred->n_total_op_fcall_ - n_total_ops;
else
n_total_ops = T::n_total_op_eq_ - n_total_ops;
// compute the expected number of invocations of operator==() or predicate
const std::size_t n_expect_ops = nsrc ? nsrc - 1 : 0;
// verify the number of applications of operator==() or predicate
rw_assert (n_total_ops <= n_expect_ops, 0, line,
"line %d: std::%s <%s%{?}, %s%{;}%{?}, %s%{;}>(\"%s\", ...) "
"%s called %zu times, %zu expected",
__LINE__, fname, itname, use_copy, outname, 0 != ppred,
funname, src, funname, n_total_ops, n_expect_ops);
}
/**************************************************************************/
template <class FwdIterator, class FwdCopyIterator,
class OutIterator, class T, class Predicate>
void test_unique (const FwdIterator &it,
const FwdCopyIterator &itc,
const OutIterator &out,
const T*,
const Predicate *ppred,
bool use_copy)
{
const char* const outname = type_name (out, (T*)0);
const char* const itname = use_copy ?
type_name (itc, (T*)0) : type_name (it, (T*)0);
const char* const fname = use_copy ? "unique_copy" : "unique";
const char* const funname = ppred ? "BinaryPredicate" : "operator==()";
rw_info (0, 0, 0,
"std::%s (%s, %2$s%{?}, %s%{;}%{?}, %s%{;})",
fname, itname, use_copy, outname, ppred, funname);
#define TEST(src, dst) \
test_unique (__LINE__, src, dst, it, itc, out, (T*)0, \
ppred, use_copy)
// +---------------- source sequence
// | +- destination sequence
// | |
// v v
TEST ("", "");
TEST ("a", "a");
TEST ("ab", "ab");
TEST ("abc", "abc");
TEST ("abcd", "abcd");
TEST ("abcde", "abcde");
TEST ("abcdef", "abcdef");
TEST ("abcdefg", "abcdefg");
TEST ("abcdefgh", "abcdefgh");
TEST ("abcdefghi", "abcdefghi");
TEST ("abcdefghij", "abcdefghij");
TEST ("abcdefghijk", "abcdefghijk");
TEST ("abcabc", "abcabc");
TEST ("abcabcabc", "abcabcabc");
TEST ("abcdabcd", "abcdabcd");
TEST ("abcdabcdabcd","abcdabcdabcd");
TEST ("aa", "a");
TEST ("aaa", "a");
TEST ("aab", "ab");
TEST ("aaa", "a");
TEST ("aaaa", "a");
TEST ("aaabb", "ab");
TEST ("aaabbb", "ab");
TEST ("abba", "aba");
TEST ("abbba", "aba");
TEST ("aaabbba", "aba");
TEST ("aaabbbaa", "aba");
TEST ("aaabbbaaa", "aba");
TEST ("aaabbbaaab", "abab");
TEST ("aaabbbaaabb", "abab");
TEST ("abbbbbaaabb", "abab");
TEST ("abaaaaaaabb", "abab");
TEST ("ababbbbbbbb", "abab");
}
/**************************************************************************/
/* extern */ int rw_opt_no_unique; // --no-unique
/* extern */ int rw_opt_no_unique_copy; // --no-unique_copy
/* extern */ int rw_opt_no_predicate; // --no-predicate
/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
template <class T, class Predicate, class FwdIterator>
void test_unique (const FwdIterator &it,
const T*,
const Predicate *ppred)
{
static const InputIter<T> input_iter (0, 0, 0);
static const OutputIter<T> output_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_unique (fwd_iter, it, fwd_iter, (T*)0, ppred, true);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
test_unique (bidir_iter, it, bidir_iter, (T*)0, ppred, true);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
test_unique (rand_iter, it, rand_iter, (T*)0, ppred, true);
}
if (rw_opt_no_output_iter) {
rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
}
else {
test_unique (fwd_iter, it, output_iter, (T*)0, ppred, true);
}
}
/**************************************************************************/
template <class T, class Predicate>
void test_unique (const T*,
const Predicate *ppred,
bool use_copy)
{
static const InputIter<T> input_iter (0, 0, 0);
static const FwdIter<T> fwd_iter (0, 0, 0);
static const BidirIter<T> bidir_iter (0, 0, 0);
static const RandomAccessIter<T> rand_iter (0, 0, 0);
rw_info (0, 0, 0,
"template <class %s%{?}, class %s%{;}%{?}, class %s%{;}> "
"%s std::%s (%1$s, %1$s%{?}, %3$s%{;}%{?}, %5$s%{;})",
use_copy ? "InputIterator" : "ForwardIterator",
use_copy, "OutputIterator", 0 != ppred, "Predicate",
use_copy ? "OutputIterator" : "ForwardIterator",
use_copy ? "unique_copy" : "unique", use_copy, 0 != ppred);
if (use_copy)
{
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_unique (input_iter, (T*)0, ppred);
}
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
if (use_copy)
test_unique (fwd_iter, (T*)0, ppred);
else
test_unique (fwd_iter, fwd_iter, fwd_iter, (T*)0, ppred, false);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
}
else {
if (use_copy)
test_unique (bidir_iter, (T*)0, ppred);
else
test_unique (bidir_iter, bidir_iter, bidir_iter,
(T*)0, ppred, false);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
}
else {
if (use_copy)
test_unique (rand_iter, (T*)0, ppred);
else
test_unique (rand_iter, rand_iter, rand_iter,
(T*)0, ppred, false);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
const BinaryPredicate pred (BinaryPredicate::op_equals);
if (rw_opt_no_unique) {
rw_note (0, __FILE__, __LINE__, "std::unique test disabled");
}
else {
test_unique ((UserClass*)0, (BinaryPredicate*)0, false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::unique predicate test disabled");
}
else {
test_unique ((UserClass*)0, &pred, false);
}
}
if (rw_opt_no_unique_copy) {
rw_note (0, __FILE__, __LINE__, "std::unique_copy test disabled");
}
else {
test_unique ((UserClass*) 0, (BinaryPredicate*)0, true);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"std::unique_copy predicate test disabled");
}
else {
test_unique ((UserClass*)0, &pred, true);
}
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.alg.unique",
0 /* no comment */, run_test,
"|-no-unique# "
"|-no-unique_copy# "
"|-no-InputIterator# "
"|-no-OutputIterator# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator# "
"|-no-predicate",
&rw_opt_no_unique,
&rw_opt_no_unique_copy,
&rw_opt_no_input_iter,
&rw_opt_no_output_iter,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter,
&rw_opt_no_predicate);
}

View File

@@ -0,0 +1,297 @@
/***************************************************************************
*
* 25.upper.bound.cpp - test exercising 25.3.3.2 [lib.upper.bound]
*
* $Id: 25.upper.bound.cpp 510970 2007-02-23 14:57:45Z 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.
*
**************************************************************************/
#include <rw/_config.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// disable implicit inclusion to work around a limitation
// of IBM VisualAge 5.0 (see PR #26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#include <algorithm> // for upper_bound()
#include <cstring> // for strlen()
#include <alg_test.h> // for iterators
#include <rw_value.h> // for UserClass
#include <driver.h> // for rw_test(), ...
/**************************************************************************/
// distinct and not Less-Than-Comparable with class UserClass (except as
// defined below) to detect unwarranted assumptions made by the
// implementation of the algorithms
struct Y
{
UserClass xval_;
// not Default-Constructible
Y (int /* dummy */, int /*dummy */): xval_ () { }
// CopyConstructible
Y (const Y &rhs): xval_ (rhs.xval_) { }
private:
void operator=(Y&); // not Assignable
};
inline conv_to_bool
operator< (const UserClass &lhs, const Y &rhs)
{
return conv_to_bool::make (lhs < rhs.xval_);
}
inline conv_to_bool
operator< (const Y &lhs, const UserClass &rhs)
{
return conv_to_bool::make (lhs.xval_ < rhs);
}
// predicate used as the Compare argument to upper_bound()
struct LessThan
{
static std::size_t funcalls_;
LessThan (int /* dummy */, int /* dummy */) {
funcalls_ = 0;
}
// return a type other than bool but one that is implicitly
// convertible to bool to detect incorrect assumptions
conv_to_bool operator() (const UserClass &lhs, const Y &rhs) {
++funcalls_;
return conv_to_bool::make (lhs < rhs.xval_);
}
conv_to_bool operator() (const Y &lhs, const UserClass &rhs) {
++funcalls_;
return conv_to_bool::make (lhs.xval_ < rhs);
}
private:
void operator= (LessThan&); // not assignable
};
std::size_t LessThan::funcalls_;
/**************************************************************************/
template <class ForwardIterator>
void test_upper_bound (int line,
const char *src_str,
char val_char,
std::size_t result_off,
std::size_t ncomp,
const ForwardIterator*,
const char *itname,
bool predicate)
{
RW_ASSERT (0 != src_str);
const std::size_t nsrc = std::strlen (src_str);
UserClass* const xsrc = UserClass::from_char (src_str, nsrc);
if (nsrc < result_off)
result_off = nsrc;
// construct the source range to pass to the algorithm
const ForwardIterator first (xsrc, xsrc, xsrc + nsrc);
const ForwardIterator last (xsrc + nsrc, xsrc + nsrc, xsrc + nsrc);
// construct the object to pass to the algorithm
// the type of the object is distinct from the iterator's value_type
// to detect unwarranted assumptions made by the implementation
Y value (0, 0 /* dummy arguments */);
value.xval_.data_.val_ = val_char;
// construct the Compare function object to pass to the algorithm
// when `predicate' is true
const LessThan comp (0, 0 /* dummy arguments */);
// reset the counter of invocations of UserClass::operator<()
UserClass::n_total_op_lt_ = 0;
// invoke the appropriate form of the algorithm, storing
// the resturned value
const ForwardIterator result = predicate
? std::upper_bound (first, last, value, comp)
: std::upper_bound (first, last, value);
// silence bogus EDG eccp 3.6 remark #550-D:
// variable was set but never used
_RWSTD_UNUSED (result);
// verify correctness
const std::size_t off = std::size_t (result.cur_ - xsrc);
rw_assert (off == result_off, 0, line,
"upper_bound(%s = \"%s\", ...%{?}%#c%{;}) ==> "
"first + %zu, got %zu",
itname, src_str, !predicate, val_char,
off, result_off);
// verify complexity
const std::size_t funcalls = predicate
? LessThan::funcalls_ : UserClass::n_total_op_lt_;
rw_assert (funcalls <= ncomp, 0, line,
"upper_bound(%s = \"%s\", ...%{?}%#c%{;}) complexity: "
"invoked predicate at most %zu times, got %zu",
itname, src_str, !predicate, val_char,
ncomp, funcalls);
delete[] xsrc;
}
/**************************************************************************/
template <class ForwardIterator>
void test_upper_bound (const ForwardIterator*,
const char *itname,
bool predicate)
{
#define TEST(str, val, off, comp) \
test_upper_bound (__LINE__, str, val, std::size_t (off), \
std::size_t (comp), (ForwardIterator*)0, \
itname, predicate)
rw_info (0, 0, 0,
"std::upper_bound (%s, %1$s, const UserClass&%{?}, %s%{;})",
itname, predicate, "LessThan");
// +--------------- source sequence
// | +--------- value argument
// | | +----- offset of the resturned iterator, -1 for end
// | | | +-- complexity: at most (log(last - first) + 1)
// | | | | comparisons (or applications of the predicate)
// | | | |
// V V V V
TEST ("", 'a', 0, 0);
TEST ("a", 'a', 1, 1);
TEST ("a", 'b', 1, 1);
TEST ("b", 'a', 0, 1);
TEST ("aa", 'a', 2, 2);
TEST ("ab", 'a', 1, 2);
TEST ("ab", 'b', 2, 2);
TEST ("bb", 'a', 0, 2);
TEST ("ace", 'a', 1, 3);
TEST ("ace", 'b', 1, 3);
TEST ("ace", 'c', 2, 3);
TEST ("ace", 'd', 2, 3);
TEST ("ace", 'e', 3, 3);
TEST ("ace", 'f', 3, 3);
TEST ("aceg", 'a', 1, 3);
TEST ("aceg", 'b', 1, 3);
TEST ("aceg", 'c', 2, 3);
TEST ("aceg", 'd', 2, 3);
TEST ("aceg", 'e', 3, 3);
TEST ("aceg", 'f', 3, 3);
TEST ("aceg", 'g', 4, 3);
TEST ("aceg", 'h', 4, 3);
}
/**************************************************************************/
static int rw_opt_no_fwd_iter;
static int rw_opt_no_bidir_iter;
static int rw_opt_no_rnd_iter;
static int rw_opt_no_predicate;
static void
test_upper_bound (bool predicate)
{
rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
"std::upper_bound (%1$s, %1$s, const UserClass&%{?}, %4$s%{;})",
"ForwardIterator", "UserClass", predicate, "Compare", predicate);
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "ForwardIterator test disabled");
}
else {
test_upper_bound ((FwdIter<UserClass>*)0, "ForwardIterator", predicate);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, 0, 0, "BidirectionalIterator test disabled");
}
else {
test_upper_bound ((BidirIter<UserClass>*)0, "BidirectionalIterator",
predicate);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, 0, 0, "RandomAccessIterator test disabled");
}
else {
test_upper_bound ((RandomAccessIter<UserClass>*)0,
"RandomAccessIterator",
predicate);
}
}
/**************************************************************************/
static int
run_test (int, char*[])
{
test_upper_bound (false);
if (rw_opt_no_predicate) {
rw_note (0, __FILE__, __LINE__,
"test of the Predicate form of std::upper_bound disabled");
}
else {
test_upper_bound (true);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.upper.bound",
0 /* no comment */,
run_test,
"|-no-Predicate# "
"|-no-ForwardIterator# "
"|-no-BidirectionalIterator# "
"|-no-RandomAccessIterator#",
&rw_opt_no_predicate,
&rw_opt_no_fwd_iter,
&rw_opt_no_bidir_iter,
&rw_opt_no_rnd_iter);
}