blob: 69b784219db4bc935b024bead63fe52e978767e3 [file] [log] [blame]
/***************************************************************************
*
* specialized.cpp - test exercising 20.4.4 [lib.specialized.algorithms]
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2001-2006 Rogue Wave Software.
*
**************************************************************************/
#include <memory>
#include <rw_alg_test.h>
#include <rw_driver.h>
/**************************************************************************/
#ifndef _RWSTD_NO_EXCEPTIONS
struct Y
{
static int count_;
static int ctor_;
static int dtor_;
static int throw_at_;
int val_;
Y (const Y &rhs) : val_ (rhs.val_) {
++ctor_;
if (count_ + 1 == throw_at_)
throw 0;
++count_;
}
Y (int val) : val_ (val) {
++ctor_;
if (count_ + 1 == throw_at_)
throw 0;
++count_;
}
~Y () {
++dtor_;
val_ = -2;
--count_;
}
private:
void operator= (const Y&); // not Assignable
};
int Y::count_;
int Y::ctor_;
int Y::dtor_;
int Y::throw_at_;
/**************************************************************************/
template <class T>
const char* type_name (volatile T*, T*) { return "volatile T*"; }
template <class T>
const char* type_name (const volatile T*, T*) { return "const volatile T*"; }
// defined as ordinary functions (as opposed to templates)
// to avoid tripping up broken compilers on argument deduction
inline const volatile int*
make_iter (const int *beg, const int*, const int*, const volatile int*)
{
return beg;
}
inline volatile Y*
make_iter (Y *beg, Y*, Y*, volatile Y*)
{
return beg;
}
/**************************************************************************/
// exercises uninitialized_copy [lib.uninitialized.copy]
// with emphasis on exception safety - the function is to have no effect
// if an exception is thrown
template <class InputIterator, class ForwardIterator>
void test_uninitialized_copy (const InputIterator &dummy,
const ForwardIterator*)
{
const char* const i1name = type_name (dummy, (int*)0);
const char* const i2name = type_name (ForwardIterator (), (Y*)0);
rw_info (0, 0, __LINE__, "std::uninitialized_copy(%s, %1$s, %s)",
i1name, i2name);
static const int a[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
const unsigned N = sizeof a / sizeof *a;
// allocate an uninitialized buffer
Y *buf = _RWSTD_STATIC_CAST (Y*, ::operator new (N * sizeof (Y)));
for (unsigned i = 0; i != N; ++i) {
Y::count_ = Y::ctor_ = Y::dtor_ = 0;
// throw during the copy construction of the i-th elem
Y::throw_at_ = i;
try {
// constructs i elements, the last ctor throws
const InputIterator first =
make_iter (a, a, a + i, dummy);
const InputIterator last =
make_iter (a + i, a, a + i, first);
const ForwardIterator result =
make_iter (buf, buf, buf + i, ForwardIterator ());
std::uninitialized_copy (first, last, result);
rw_assert (i == 0, 0, __LINE__,
"%zu. expected exception not thrown", i);
}
catch (int) {
// ctor throws an int, this is what's expected
}
catch (...) {
rw_assert (0, 0, __LINE__,
"%zu. exception of an unexpected type thrown", i);
}
// verify that all constructed elements were destroyed
rw_assert (Y::count_ == 0, 0, __LINE__,
"%zu. %d elements not destroyed", i, Y::count_);
// verify that the expected number of ctor and dtor calls were made
rw_assert (Y::ctor_ == Y::throw_at_, 0, __LINE__,
"%zu. %d ctor calls expected, got %d",
i, Y::throw_at_, Y::ctor_);
rw_assert (i ? Y::dtor_ + 1 == Y::throw_at_ : true, 0, __LINE__,
"%zu. %d dtor calls expected, got %d",
i, Y::throw_at_ - 1, Y::dtor_);
}
::operator delete (buf);
}
/**************************************************************************/
// exercises 20.4.4.2 and 3 - uninitialized_fill [lib.uninitialized.fill]
// and uninitialized_fill_n [lib.uninitialized.fill_n] with emphasis on
// exception safety - the function is to have no effect if an exception
// is thrown
template <class ForwardIterator>
void test_uninitialized_fill (const ForwardIterator*, bool test_count)
{
const char* const itname = type_name (ForwardIterator (), (Y*)0);
rw_info (0, 0, __LINE__,
"std::uninitialized_fill%{?}_n%{;}(%s, %{?}size_t%{:}%2$s%{;}, "
"const int&)", test_count, itname, test_count);
const unsigned N = 32;
// allocate an uninitialized buffer
Y *buf = _RWSTD_STATIC_CAST (Y*, ::operator new (N * sizeof (Y)));
for (unsigned i = 0; i != N; ++i) {
// prevent ctor below from throwing
Y::throw_at_ = -1;
// create a temporary and reset counters (in that order)
Y val (i);
Y::count_ = Y::ctor_ = Y::dtor_ = 0;
// throw during the copy construction of the i-th elem
Y::throw_at_ = i;
try {
// copy-constructs i elements, the last copy ctor throws
const ForwardIterator first =
make_iter (buf, buf, buf + i, ForwardIterator ());
if (test_count) {
std::uninitialized_fill_n (first, i, val);
}
else {
const ForwardIterator last =
make_iter (buf + i, buf, buf + i, first);
std::uninitialized_fill (first, last, val);
}
rw_assert (i == 0, 0, __LINE__,
"%zu. expected exception not thrown", i);
}
catch (int) {
// ctor throws an int, this is what's expected
}
catch (...) {
rw_assert (0, 0, __LINE__,
"%zu. exception of an unexpected type thrown", i);
}
// verify that all constructed elements were destroyed
rw_assert (Y::count_ == 0, 0, __LINE__,
"%zu. %d elements not destroyed", i, Y::count_);
// verify that the expected number of ctor and dtor calls were made
rw_assert (Y::ctor_ == Y::throw_at_, 0, __LINE__,
"%zu. %d ctor calls expected, got %d",
i, Y::throw_at_, Y::ctor_);
rw_assert (i ? Y::dtor_ + 1 == Y::throw_at_ : true, 0, __LINE__,
"%d. %d dtor calls expected, got %d",
i, Y::throw_at_ - 1, Y::dtor_);
}
::operator delete (buf);
}
/**************************************************************************/
int opt_copy;
int opt_fill;
int opt_fill_n;
int opt_input_iter;
int opt_fwd_iter;
int opt_bidir_iter;
int opt_rnd_iter;
int opt_volatile_ptr;
template <class InputIterator>
void test_uninitialized_copy (const InputIterator &dummy)
{
if (-1 < opt_fwd_iter)
test_uninitialized_copy (dummy, (FwdIter<Y>*)0);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_copy (dummy, (BidirIter<Y>*)0);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_rnd_iter)
test_uninitialized_copy (dummy, (RandomAccessIter<Y>*)0);
else
rw_note (-1 > opt_rnd_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
typedef volatile Y* VolatilePointer;
test_uninitialized_copy (dummy, (VolatilePointer*)0);
}
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
/**************************************************************************/
static int
run_test (int, char**)
{
typedef const volatile int* ConstVolatilePointer;
typedef /* */ volatile Y* VolatilePointer;
if (-1 < opt_copy) {
if (-1 < opt_input_iter)
test_uninitialized_copy (InputIter<int>(0, 0, 0));
else
rw_note (-1 > opt_input_iter--, 0, __LINE__,
"InputIterator tests disabled");
if (-1 < opt_fwd_iter)
test_uninitialized_copy (ConstFwdIter<int>());
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_copy (ConstBidirIter<int>());
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_rnd_iter)
test_uninitialized_copy (ConstRandomAccessIter<int>());
else
rw_note (-1 > opt_rnd_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr)
test_uninitialized_copy (ConstVolatilePointer ());
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_copy disabled");
//////////////////////////////////////////////////////////////////
if (-1 < opt_fill) {
if (-1 < opt_fwd_iter)
test_uninitialized_fill ((FwdIter<Y>*)0, false);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((BidirIter<Y>*)0, false);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((RandomAccessIter<Y>*)0, false);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
test_uninitialized_fill ((VolatilePointer*)0, false);
}
else
rw_note (-1 > opt_volatile_ptr++,
0, 0, "volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_fill disabled");
//////////////////////////////////////////////////////////////////
if (-1 < opt_fill) {
if (-1 < opt_fwd_iter)
test_uninitialized_fill ((FwdIter<Y>*)0, true);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((BidirIter<Y>*)0, true);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((RandomAccessIter<Y>*)0, true);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
test_uninitialized_fill ((VolatilePointer*)0, true);
}
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_fill disabled");
return 0;
}
#else // _RWSTD_NO_EXCEPTIONS
static int
run_test (int, char**)
{
rw_note (0, 0, 0,
"exceptions disabled (_RWSTD_NO_EXCEPTIONS #defined), "
"cannot test");
return 0;
}
#endif // _RWSTD_NO_EXCEPTIONS
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.specialized.algorithms",
0 /* no comment */,
run_test,
"|-uninitialized_copy~ "
"|-uninitialized_fill~ "
"|-uninitialized_fill_n~ "
"|-InputIterator~ "
"|-ForwardIterator~ "
"|-BidirectionalIterator~ "
"|-RandomAccessIterator~ "
"|-volatile-pointer",
&opt_copy,
&opt_fill,
&opt_fill_n,
&opt_input_iter,
&opt_fwd_iter,
&opt_bidir_iter,
&opt_rnd_iter,
&opt_volatile_ptr);
}