The attached file contains my attempt to exercise copy and copy_backward
algorithms using new test driver.
Martin Sebor wrote:
Yes, the to_string() helper function is absent from the new driver. There is no
equivalent for class X, but the best way to handle it, I think, is along the same
lines as in 25.adjacent.find.cpp, i.e., > use printable characters instead
of integers as values for X.val_. Then we can easily print out the sequence(s) in
diagnostics.
In this version I just removed all references to tempstr structure - it was
used for very detailed diagnostic messages only - and I changed these messages.
With best wishes,
Anton Pevtsov.
-----Original Message-----
From: Martin Sebor [mailto:[EMAIL PROTECTED]
Sent: Thursday, December 01, 2005 03:42
To: [email protected]
Subject: Re: questions about the lib.alg.copy test
Martin Sebor wrote:
Anton Pevtsov wrote:
[...]
2. The copy algorithm can work in case when the destination range
overlaps the source range (of course, first position of the source
range should not be contained in the destination range). Current
version doesn't contain special test for this case, but I prefer to
have such test. What do you think about it?
The requirement in 25.2.1, p3 is that "result shall not be in the
range [first, last)." The algorithm doesn't detect violations of this
requirement but it probably should in debug mode. This would be a
useful enhancement in general. Let me file an enhancement for it.
Here's the issue: http://issues.apache.org/jira/browse/STDCXX-78
Martin
/***************************************************************************
*
* copy.cpp - test exercising 25.2.1 [lib.alg.copy]
*
* $Id: //stdlib/dev/tests/stdlib/algorithm/copy.cpp#29 $
*
***************************************************************************
*
* Copyright (c) 1994-2005 Quovadx, Inc. All Rights Reserved.
*
* This computer software is owned by Quovadx, Inc. and is protected by
* U.S. copyright laws and other laws and by international treaties.
* This computer software is furnished by Quovadx, Inc., pursuant to a
* written license agreement and may be used, copied, transmitted, and
* stored only in accordance with the terms of such license agreement and
* with the inclusion of the above copyright notice. This computer
* software or any other copies thereof may not be provided or otherwise
* made available to any other person.
*
*
* U.S. Government Restricted Rights.
*
* This computer software: (a) was developed at private expense and is in
* all respects the proprietary information of Quovadx, Inc.; (b) was not
* developed with government funds; (c) is a trade secret of Quovadx,
* Inc. for all purposes of the Freedom of Information Act; and (d) is a
* commercial item and thus, pursuant to Section 12.212 of the Federal
* Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
* Government's use, duplication or disclosure of the computer software
* is subject to the restrictions set forth by Quovadx, Inc.
*
**************************************************************************/
#include <algorithm> // for copy
#include <cstddef> // for size_t
#include <alg_test.h>
#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, "%s std::copy (%s, %s, %s)",
it2name, it1name, 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].val_ == dst[j].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].val_, dst[j].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, "%s std::copy_backward (%s, %s, %s)",
it2name, it1name, 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].val_ == dst[j].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].val_, dst[j].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<X>((X*)0, (X*)0, (X*)0), (X*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_copy (N, dummy, FwdIter<X>(), (X*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy (N, dummy, BidirIter<X>(), (X*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy (N, dummy, RandomAccessIter<X>(), (X*)0);
}
}
static
void test_copy (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class InputIterator, class OutputIterator> "
"OutputIterator std::copy (InputIterator, "
"InputIterator, OutputIterator)");
if (rw_opt_no_input_iter) {
rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
}
else {
test_copy (N, InputIter<X>((X*)0, (X*)0, (X*)0), (X*)0);
}
if (rw_opt_no_fwd_iter) {
rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
}
else {
test_copy (N, FwdIter<X>(), (X*)0);
}
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy (N, BidirIter<X>(), (X*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy (N, RandomAccessIter<X>(), (X*)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<X>(), (X*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy_backward (N, dummy, RandomAccessIter<X>(), (X*)0);
}
}
static
void test_copy_backward (const std::size_t N)
{
rw_info (0, 0, 0,
"template <class BidirectionalIterator1, class "
"BidirectionalIterator2> BidirectionalIterator2 "
"std::copy_backward (BidirectionalIterator1, "
"BidirectionalIterator1, BidirectionalIterator2)");
if (rw_opt_no_bidir_iter) {
rw_note (0, __FILE__, __LINE__,
"BidirectionalIterator test disabled");
}
else {
test_copy_backward (N, BidirIter<X>(), (X*)0);
}
if (rw_opt_no_rnd_iter) {
rw_note (0, __FILE__, __LINE__,
"RandomAccessIterator test disabled");
}
else {
test_copy_backward (N, RandomAccessIter<X>(), (X*)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);
}