| /*************************************************************************** |
| * |
| * specialized.cpp - test exercising 20.4.4 [lib.specialized.algorithms] |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Copyright 2005-2006 The Apache Software Foundation or its licensors, |
| * as applicable. |
| * |
| * Copyright 2001-2006 Rogue Wave Software. |
| * |
| * Licensed 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. |
| * |
| **************************************************************************/ |
| |
| #include <memory> |
| #include <alg_test.h> |
| #include <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); |
| } |