| /*************************************************************************** |
| * |
| * 23.vector.cons.cpp - test exercising [lib.vector.cons] |
| * |
| * $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 2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| #include <memory> // for placement operator new() |
| #include <vector> // for vector |
| |
| #include <cstddef> // for size_t |
| |
| #include <rw_alg_test.h> |
| #include <rw_value.h> // for UserClass |
| #include <rw_driver.h> |
| #include <rw_new.h> |
| |
| /**************************************************************************/ |
| |
| static unsigned rw_opt_nloops; |
| static int rw_opt_no_int_spec; |
| static int rw_opt_no_short_spec; |
| static int rw_opt_no_types; |
| static int rw_opt_no_signatures; |
| static int rw_opt_no_ctors; |
| |
| /**************************************************************************/ |
| |
| template <class RandomAccessIterator, |
| class T, |
| class Reference, |
| class Pointer, |
| class Difference> |
| struct test_iterator |
| { |
| test_iterator (); |
| }; |
| |
| /**************************************************************************/ |
| |
| // outlined to prevent gcc -Winline warnings |
| template <class RandomAccessIterator, |
| class T, |
| class Reference, |
| class Pointer, |
| class Difference> |
| test_iterator<RandomAccessIterator, T, Reference, Pointer, Difference>:: |
| test_iterator () |
| { |
| static int i; // zeroed out |
| if (++i) // prevent "unreachable code" warnings |
| return; // compile only |
| |
| // exercise RandomAccessIterator requirements |
| |
| RandomAccessIterator it = RandomAccessIterator (); |
| RandomAccessIterator it_cpy (it); |
| |
| Difference d (it - it); |
| |
| RandomAccessIterator &it_ref1 = ++it; |
| const RandomAccessIterator &it_ref2 = it++; |
| |
| RandomAccessIterator &it_ref3 = --it; |
| const RandomAccessIterator &it_ref4 = it--; |
| |
| RandomAccessIterator &it_ref5 = it += 1; |
| it_cpy = it + d; |
| it_cpy = d + it; |
| |
| RandomAccessIterator &it_ref6 = it -= 1; |
| it_cpy = it - d; |
| |
| T t (it [d]); |
| |
| Reference ref1 (*it); |
| Reference ref2 (*it++); |
| |
| bool b (it == it); |
| b = it != it; |
| b = it > it; |
| b = it >= it; |
| b = it <= it; |
| |
| |
| _RWSTD_UNUSED (it); |
| _RWSTD_UNUSED (it_cpy); |
| _RWSTD_UNUSED (it_ref1); |
| _RWSTD_UNUSED (it_ref2); |
| _RWSTD_UNUSED (it_ref3); |
| _RWSTD_UNUSED (it_ref4); |
| _RWSTD_UNUSED (it_ref5); |
| _RWSTD_UNUSED (it_ref6); |
| _RWSTD_UNUSED (d); |
| _RWSTD_UNUSED (t); |
| _RWSTD_UNUSED (ref1); |
| _RWSTD_UNUSED (ref2); |
| _RWSTD_UNUSED (b); |
| } |
| |
| /***************************************************************************/ |
| |
| // verify that nested types are properly defined |
| template <class Vector, class T, class Allocator> |
| void test_types (Vector*, T*, Allocator) |
| { |
| #define TEST_TYPE(T, vectorT) { \ |
| T *t = (typename Vector::vectorT*)0; \ |
| _RWSTD_UNUSED (t); \ |
| } |
| |
| #define TEST_REFERENCE(T, vectorT) { \ |
| typename Vector::value_type v; \ |
| T t = v; \ |
| _RWSTD_UNUSED (t); \ |
| } |
| |
| // verify nested types |
| TEST_TYPE (T, value_type); |
| TEST_TYPE (Allocator, allocator_type); |
| TEST_TYPE (typename Allocator::pointer, pointer); |
| TEST_TYPE (typename Allocator::const_pointer, const_pointer); |
| |
| #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC |
| |
| typedef std::reverse_iterator<typename Vector::iterator> |
| ReverseIterator; |
| typedef std::reverse_iterator<typename Vector::const_iterator> |
| ConstReverseIterator; |
| |
| #else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) |
| |
| typedef std::reverse_iterator<typename Vector::iterator, |
| std::random_access_iterator_tag, T /*non-const T&, non-const T* */> |
| ReverseIterator; |
| |
| typedef std::reverse_iterator<typename Vector::const_iterator, |
| std::random_access_iterator_tag, T, const T&, const T*> |
| ConstReverseIterator; |
| |
| #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC |
| |
| TEST_TYPE (ReverseIterator, reverse_iterator); |
| TEST_TYPE (ConstReverseIterator, const_reverse_iterator); |
| |
| test_iterator<typename Vector::iterator, T, T&, T*, std::ptrdiff_t> |
| ti; // exercise iterator requirements |
| test_iterator<typename Vector::const_iterator, T, const T&, const T*, |
| std::ptrdiff_t> |
| tci; // exercise iterator requirements |
| |
| test_iterator<ReverseIterator, T, T&, T*, std::ptrdiff_t> |
| tri; // exercise iterator requirements |
| test_iterator<ConstReverseIterator, T, const T&, const T*, std::ptrdiff_t> |
| tcri; // exercise iterator requirements |
| |
| _RWSTD_UNUSED (ti); _RWSTD_UNUSED (tci); |
| _RWSTD_UNUSED (tri); _RWSTD_UNUSED (tcri); |
| |
| // special treatment |
| TEST_REFERENCE (typename Allocator::reference, reference); |
| TEST_REFERENCE (typename Allocator::const_reference, const_reference); |
| } |
| |
| /**************************************************************************/ |
| |
| // verify that member functions are properly defined |
| template <class Vector, class T, class Allocator> |
| void test_signatures (Vector*, T*, Allocator) |
| { |
| // verify that a member function is accessible and has the appropriate |
| // signature, including return type and exception specification |
| #define MEMFUN(result, name, arg_list) do { \ |
| result (Vector::*pf) arg_list = &Vector::name; \ |
| _RWSTD_UNUSED (pf); \ |
| } while (0) |
| |
| MEMFUN (Vector&, operator=, (const Vector&)); |
| |
| // helpers to work around a SunPro 5.3 bug (see PR #25972) |
| typedef typename Vector::size_type SizeType; |
| typedef typename Vector::value_type ValueType; |
| typedef typename Vector::iterator Iterator; |
| |
| // verify signatures of iterator accessors |
| MEMFUN (typename Vector::iterator, begin, ()); |
| MEMFUN (typename Vector::const_iterator, begin, () const); |
| MEMFUN (typename Vector::iterator, end, ()); |
| MEMFUN (typename Vector::const_iterator, end, () const); |
| |
| // verify signatures of reverse iterator accessors |
| MEMFUN (typename Vector::reverse_iterator, rbegin, ()); |
| MEMFUN (typename Vector::const_reverse_iterator, rbegin, () const); |
| MEMFUN (typename Vector::reverse_iterator, rend, ()); |
| MEMFUN (typename Vector::const_reverse_iterator, rend, () const); |
| |
| // verify signatures of capacity accessors |
| MEMFUN (SizeType, size, () const); |
| MEMFUN (SizeType, max_size, () const); |
| MEMFUN (void, resize, (SizeType, ValueType)); |
| MEMFUN (SizeType, capacity, () const); |
| MEMFUN (bool, empty, () const); |
| MEMFUN (void, reserve, (SizeType)); |
| |
| // verify signature of the element access functions |
| MEMFUN (const T&, operator[], (SizeType) const); |
| MEMFUN (T&, operator[], (SizeType)); |
| MEMFUN (const T&, at, (SizeType) const); |
| MEMFUN (T&, at, (SizeType)); |
| MEMFUN (const T&, front, () const); |
| MEMFUN (T&, front, ()); |
| MEMFUN (const T&, back, () const); |
| MEMFUN (T&, back, ()); |
| |
| // verify signatures of modifiers |
| MEMFUN (void, push_back, (const T&)); |
| MEMFUN (void, pop_back, ()); |
| |
| MEMFUN (Iterator, insert, (Iterator, const T&)); |
| |
| MEMFUN (void, insert, (Iterator, SizeType, const T&)); |
| |
| #if !defined (_MSC_VER) || _MSC_VER >= 1300 |
| // member function template insert |
| MEMFUN (void, insert, (Iterator, InputIter<T>, InputIter<T>)); |
| #endif // !defined (_MSC_VER) || _MSC_VER >= 1300 |
| |
| MEMFUN (Iterator, erase, (Iterator)); |
| MEMFUN (Iterator, erase, (Iterator, Iterator)); |
| |
| MEMFUN (void, swap, (Vector&)); |
| MEMFUN (void, clear, ()); |
| |
| #if !defined (_MSC_VER) || _MSC_VER > 1300 |
| |
| #define FUN(result, name, arg_list) do { \ |
| result (*pf) arg_list = &name; \ |
| _RWSTD_UNUSED (pf); \ |
| } while (0) |
| |
| // verify signatures of non-member functions |
| FUN (bool, std::operator==, (const Vector&, const Vector&)); |
| FUN (bool, std::operator<, (const Vector&, const Vector&)); |
| FUN (bool, std::operator!=, (const Vector&, const Vector&)); |
| FUN (bool, std::operator>, (const Vector&, const Vector&)); |
| FUN (bool, std::operator>=, (const Vector&, const Vector&)); |
| FUN (bool, std::operator<=, (const Vector&, const Vector&)); |
| FUN (void, std::swap, (Vector&, Vector&)); |
| |
| #else // MSVC <= 7.0 |
| |
| // working around a bug in MSVC 7 and prior (see PR #26625) |
| |
| if (0 /* compile only */) { |
| |
| Vector *pv = 0; |
| const Vector *pcv = 0; |
| |
| bool b; |
| b = std::operator== (*pcv, *pcv); |
| b = std::operator< (*pcv, *pcv); |
| b = std::operator!= (*pcv, *pcv); |
| b = std::operator> (*pcv, *pcv); |
| b = std::operator>= (*pcv, *pcv); |
| b = std::operator<= (*pcv, *pcv); |
| std::swap (*pv, *pv); |
| } |
| |
| #endif // MSVC <= 7.0 |
| |
| } |
| |
| /**************************************************************************/ |
| |
| // exercise [lib.vector.cons] and vector<>::operator=() |
| // focus on the correct construction and destruction of values |
| void test_ctors () |
| { |
| typedef std::vector<UserClass, std::allocator<UserClass> > Vector; |
| |
| if (1) { |
| |
| rw_info (0, 0, 0, |
| "std::vector<UserClass>::vector(size_type, " |
| "const_reference, const allocator_type&)"); |
| |
| rw_info (0, 0, 0, "std::vector<UserClass>::vector(const vector&)"); |
| |
| // reset function call counters |
| UserClass::reset_totals (); |
| |
| // total number of objects of type UserClass in existence |
| const std::size_t x_count = UserClass::count_; |
| |
| for (Vector::size_type i = 0; i != rw_opt_nloops; ++i) { |
| |
| rw_assert (UserClass::count_ == x_count, 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference); " |
| "leaked %zu objects of value_type", |
| UserClass::count_ - x_count); |
| |
| // reset function call counters |
| UserClass::reset_totals (); |
| |
| const UserClass val; |
| |
| // initialize a vector with `i' copies of `val' |
| const Vector v0 (i, val); |
| rw_assert ( i == v0.size () |
| && v0.begin () + i == v0.end () |
| && v0.rbegin () + i == v0.rend (), |
| 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference)"); |
| |
| // verify that the vector ctor calls only copy ctor |
| // of UserClass and anly the given number of times each |
| rw_assert (UserClass::is_total (i + 1, 1, i, 0, 0, 0), 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference); " |
| "called default/copy ctor and operator=() %zu, %zu, " |
| "and %zu times, respectively, 0, %zu, 0 expected", |
| UserClass::n_total_def_ctor_ - 1, |
| UserClass::n_total_copy_ctor_, |
| UserClass::n_total_op_assign_, i); |
| |
| // create a copy |
| Vector v1 (v0); |
| rw_assert ( i == v1.size () |
| && v1.begin () + i == v1.end () |
| && v1.rbegin () + i == v1.rend (), |
| 0, __LINE__, |
| "vector<UserClass>::vector(const vector&)"); |
| |
| // verify that the vector copy ctor calls only copy ctor |
| // of UserClass and anly the given number of times each |
| rw_assert (UserClass::is_total (2 * i + 1, 1, 2 * i, 0, 0, 0), |
| 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference); " |
| "called default/copy ctor and operator=() %zu, %zu, " |
| "and %zu times, respectively, 0, %zu, 0 expected", |
| UserClass::n_total_def_ctor_ - 1, |
| UserClass::n_total_copy_ctor_, |
| UserClass::n_total_op_assign_, i); |
| |
| // exercise vector<>operator=(const vector&) |
| Vector v2 (i, val); |
| |
| for (Vector::size_type j = 0; j != rw_opt_nloops; ++j) { |
| |
| Vector v3 (j, val); |
| |
| // assign a vector (of a possibly unequal size) |
| v3 = v2; |
| rw_assert (v3.size () == v2.size (), 0, __LINE__, |
| "%zu. vector<UserClass>::operator=(const vector&)", |
| j); |
| |
| rw_assert (v3 == v2, 0, __LINE__, |
| "%zu. vector<UserClass>::operator=(const vector&)", |
| j); |
| } |
| |
| #ifndef _RWSTD_NO_EXCEPTIONS |
| |
| // exercise vector exception safety |
| |
| bool thrown = false; |
| |
| // create a suitably aligned buffer in which to construct |
| // the vector object |
| union { |
| void *pad; |
| char buf [sizeof (Vector)]; |
| } buf = { 0 }; |
| |
| std::size_t x_count_save = UserClass::count_; |
| |
| try { |
| // have UserClass copy ctor throw an exception during |
| // the copying of the last value |
| UserClass::copy_ctor_throw_count_ = |
| UserClass::n_total_copy_ctor_ + i; |
| |
| // create a vector object, throw an exception |
| // expect vector ctor to destroy any values |
| // constructed prior to throwing the exception |
| // and to free all already allocated memory |
| |
| // use placement new to prevent vector destruction |
| // at scope exit (the object should be destroyed |
| // during stack unwinding instead) |
| Vector *p = new (&buf.buf) Vector (i, val); |
| |
| // destroy explicitly if ctor doesn't propagate exception |
| |
| #if !defined (__HP_aCC) || _RWSTD_HP_aCC_MINOR > 3800 |
| |
| p->~Vector (); |
| #else |
| // work around aCC bug (see PR #25356) |
| p->~vector (); |
| |
| #endif // HP aCC |
| |
| } |
| catch (...) { |
| thrown = true; |
| } |
| |
| // no exception thrown if (i == 0), no elements constructed |
| rw_assert (i == 0 || thrown, 0, __LINE__, |
| "logic error: failed to throw"); |
| |
| rw_assert (x_count_save == UserClass::count_, 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference) " |
| "leaked %zu value(s) of %zu after an exception", |
| UserClass::count_ - x_count_save, i); |
| |
| // exercise vector<>::vector(const vector&) |
| thrown = false; |
| x_count_save = UserClass::count_; |
| |
| try { |
| // have UserClass copy ctor throw an exception during |
| // the copying of the last value |
| UserClass::copy_ctor_throw_count_ = |
| UserClass::n_total_copy_ctor_ + i; |
| |
| // use placement new to prevent vector destruction |
| // at scope exit (the object should be destroyed |
| // during stack unwinding instead) |
| Vector *p = new (&buf) Vector (v1); |
| |
| // destroy explicitly if ctor doesn't propagate exception |
| |
| #if !defined (__HP_aCC) || _RWSTD_HP_aCC_MINOR > 3800 |
| |
| p->~Vector (); |
| #else |
| // work around aCC bug (see PR #25356) |
| p->~vector (); |
| |
| #endif // HP aCC |
| |
| } |
| catch (...) { |
| // vector should have been destroyed |
| thrown = true; |
| } |
| |
| // no exception thrown if (i == 0), no elements constructed |
| rw_assert(i == 0 || thrown, 0, __LINE__, |
| "logic error: failed to throw"); |
| |
| rw_assert (x_count_save == UserClass::count_, 0, __LINE__, |
| "vector<UserClass>::vector(const vector&) leaked " |
| "%zu value(s) of %zu after an exception", |
| UserClass::count_ - x_count_save, i); |
| |
| |
| // disable exceptions |
| UserClass::copy_ctor_throw_count_ = std::size_t (-1); |
| |
| // remember v1's size and capacity |
| const Vector::size_type v1_size = v1.size (); |
| const Vector::size_type v1_cap = v1.capacity (); |
| |
| // create and initialize vector with some values |
| // make sure v3's capacity is greater than that of v1 |
| // (otherwise the assignment isn't exception safe since |
| // it simply overwrites existing values for efficiency) |
| const Vector v3 (v1_cap * 2, val); |
| |
| // exrecise vector<>::operator=(const vector&) |
| thrown = false; |
| x_count_save = UserClass::count_; |
| |
| try { |
| // have UserClass copy ctor throw an exception during |
| // the copying of the last value |
| UserClass::copy_ctor_throw_count_ = |
| UserClass::n_total_copy_ctor_ + v3.size (); |
| |
| // assign over the existing elements, the last copy ctor or |
| // operator=() throws, destroying all values assigned so far |
| v1 = v3; |
| } |
| catch (...) { |
| // original vector must remain unchanged |
| thrown = true; |
| } |
| |
| // disable exceptions |
| UserClass::copy_ctor_throw_count_ = std::size_t (-1); |
| |
| rw_assert (i == 0 || thrown, 0, __LINE__, |
| "logic error: failed to throw"); |
| |
| // verify that no values leaked |
| rw_assert (x_count_save == UserClass::count_, 0, __LINE__, |
| "vector<UserClass>::vector(const vector&) leaked " |
| "%zu value(s) of %zu after an exception", |
| UserClass::count_ - x_count_save, i); |
| |
| // verify that the size of the left hand size operand |
| // of the assignment hasn't changed |
| rw_assert (v1.size () == v1_size && v1.capacity () == v1_cap, |
| 0, __LINE__, "vector<UserClass>::operator=" |
| "(const vector&) changed size of *this from " |
| "%zu to %zu after exception", |
| i / 2, v3.size ()); |
| |
| #endif // _RWSTD_NO_EXCEPTIONS |
| |
| // vectors go out of scope, must destroy all elements |
| } |
| } |
| } |
| |
| // exercise [lib.vector.cons] |
| template <class Vector, class T, class Alloc> |
| void test_ctors (Vector*, T*, Alloc alloc) |
| { |
| if (1) { |
| |
| rw_info (0, 0, 0, |
| "std::vector<UserClass>::vector(const allocator_type&)"); |
| |
| // verify default ctor arguments |
| Vector v0; |
| Vector v1 (alloc); |
| |
| rw_assert ( 0 == v0.size () |
| && v0.empty () && v0.begin () == v0.end () |
| && v0.rbegin () == v0.rend (), 0, __LINE__, |
| ("vector<UserClass>::vector()")); |
| |
| rw_assert ( 0 == v1.size () |
| && v1.empty () && v1.begin () == v1.end () |
| && v1.rbegin () == v1.rend (), 0, __LINE__, |
| "vector<UserClass>::vector()"); |
| } |
| |
| if (1) { |
| |
| rw_info (0, 0, 0, |
| "std::vector<UserClass>::vector(size_type, " |
| "const_reference, const allocator_type&)"); |
| |
| for (typename Vector::size_type i = 0; i != rw_opt_nloops; ++i) { |
| |
| const T val = T (i); |
| |
| Vector v0 (i, val); |
| Vector v1 (i, val, alloc); |
| |
| rw_assert ( i == v0.size () |
| && v0.begin () + i == v0.end () |
| && v0.rbegin () + i == v0.rend (), |
| 0, __LINE__, |
| "vector<UserClass>::vector" |
| "(size_type, const_reference)"); |
| |
| rw_assert ( i == v1.size () |
| && v1.begin () + i == v1.end () |
| && v1.rbegin () + i == v1.rend (), |
| 0, __LINE__, |
| "vector<UserClass>::vector(size_type, " |
| "const_reference, const allocator_type&)"); |
| |
| bool success = true; |
| for (typename Vector::size_type j = 0; j != i; ++j) { |
| if (!(success = v0 [j] == val)) |
| break; |
| if (!(success = v1 [j] == val)) |
| break; |
| } |
| |
| rw_assert (success, 0, __LINE__, |
| "vector<UserClass>::vector(size_type, const_reference); " |
| "all elements initialized"); |
| } |
| } |
| |
| #if !defined (_MSC_VER) || _MSC_VER >= 1300 |
| |
| if (1) { |
| |
| rw_info (0, 0, 0, |
| "template <class InputIterator> std::vector<UserClass>::vector" |
| "(InputIterator, InputIterator)"); |
| |
| bool success = true; |
| |
| // allocate nloops elements, do not initialize |
| typename Vector::value_type *vals = alloc.allocate (rw_opt_nloops); |
| |
| for (typename Vector::size_type i = 0; i != rw_opt_nloops; ++i) { |
| |
| // construct an element at then end of array |
| alloc.construct (vals + i, typename Alloc::value_type (i)); |
| |
| // verify ctor with a strict InputIterator |
| InputIter<T> first (vals, vals, vals + i); |
| InputIter<T> last (vals + i, vals + i, vals + i); |
| |
| const Vector v0 (first, last); |
| |
| // reset iterators since they are single-pass and their |
| // copies have been passed through by the ctor above |
| first = InputIter<T>(vals, vals, vals + i); |
| last = InputIter<T>(vals + i, vals + i, vals + i); |
| |
| const Vector v1 (first, last, alloc); |
| |
| if ( i != v0.size () |
| || (!(i && !v0.empty () || !i && v0.empty ())) |
| || (i != v1.size ()) |
| || (!(i && !v1.empty () || !i && v1.empty ()))) |
| success = false; |
| |
| // verify size() and empty() |
| rw_assert (i == v0.size (), 0, __LINE__, |
| "size () == %zu, got %zu", i, v0.size ()); |
| |
| rw_assert (i && !v0.empty () || !i && v0.empty (), |
| 0, __LINE__, "size () == %zu, empty () == %d", |
| v0.size (), v0.empty ()); |
| |
| rw_assert (i == v1.size (), 0, __LINE__, |
| "size () == %zu, got %zu", i, v1.size ()); |
| |
| rw_assert (i && !v1.empty () || !i && v1.empty (), |
| 0, __LINE__, "size () == %zu, empty () == %d", |
| v1.size (), v1.empty ()); |
| } |
| |
| rw_assert (success, 0, __LINE__, |
| "template <class InputIterator> " |
| "std::vector<UserClass>::vector" |
| "(InputIterator, InputIterator)"); |
| |
| // destroy and deallocate... |
| for (typename Vector::size_type j = 0; j != rw_opt_nloops; ++j) |
| alloc.destroy (vals + j); |
| |
| alloc.deallocate (vals, rw_opt_nloops); |
| } |
| |
| #endif // !defined (_MSC_VER) || _MSC_VER >= 1300 |
| |
| } |
| |
| /**************************************************************************/ |
| |
| static int |
| run_test (int /* argc */, char** /* argv */) |
| { |
| static int int_noted = 0; |
| static int short_noted = 0; |
| static int types_noted = 0; |
| static int sign_noted = 0; |
| static int ctors_noted = 0; |
| |
| #ifndef _RWSTD_NO_EXCEPTIONS |
| |
| try { |
| // throw an exception to initialize the lib (allocates |
| // memory that's never deallocated; shows up as leaks) |
| _RW::__rw_throw (_RWSTD_ERROR_LOGIC_ERROR, "", ""); |
| } |
| catch (...) { |
| } |
| |
| #endif // _RWSTD_NO_EXCEPTIONS |
| |
| // for convenience (in case default template arguments are disabled) |
| #define VECTOR(T) std::vector<T, std::allocator<T> > |
| |
| #define TEST(what, T) \ |
| do { \ |
| /* establish a checkpoint for memory leaks */ \ |
| rwt_check_leaks (0, 0); \ |
| test_ ##what ((VECTOR (T)*)0, (T*)0, std::allocator<T>()); \ |
| /* verify that no memory leaked */ \ |
| std::size_t nbytes; \ |
| const std::size_t nblocks = rwt_check_leaks (&nbytes, 0); \ |
| rw_assert (!nblocks && !nbytes, 0, __LINE__, \ |
| #what " test leaked %lu bytes in %lu blocks", \ |
| nbytes, nblocks); \ |
| } while (0) |
| |
| if (rw_opt_no_int_spec) { |
| rw_note (int_noted++, 0, __LINE__, |
| "int specializations test disabled."); |
| } |
| else { |
| // exercise vector and its default template argument |
| if (rw_opt_no_types) { |
| rw_note (types_noted++, 0, __LINE__, "Types test disabled."); |
| } |
| else { |
| TEST (types, int); |
| } |
| |
| if (rw_opt_no_signatures) { |
| rw_note (sign_noted++, 0, __LINE__, "Signatures test disabled."); |
| } |
| else { |
| TEST (signatures, int); |
| } |
| |
| if (rw_opt_no_ctors) { |
| rw_note (ctors_noted++, 0, __LINE__, "Ctors test disabled."); |
| } |
| else { |
| TEST (ctors, int); |
| } |
| } |
| |
| // exercise vector with a template argument other than the default |
| #undef VECTOR |
| #define VECTOR(T, A) std::vector<T, A<T> > |
| |
| #undef TEST |
| #define TEST(what,T,A) test_ ##what ((VECTOR (T, A)*)0, (T*)0, A<T>()) |
| |
| if (rw_opt_no_short_spec) { |
| rw_note (short_noted++, 0, __LINE__, |
| "short specializations test disabled."); |
| } |
| else { |
| if (rw_opt_no_types) { |
| rw_note (types_noted++, 0, __LINE__, "Types test disabled."); |
| } |
| else { |
| TEST (types, short, std::allocator); |
| } |
| |
| if (rw_opt_no_signatures) { |
| rw_note (sign_noted++, 0, __LINE__, "Signatures test disabled."); |
| } |
| else { |
| TEST (signatures, short, std::allocator); |
| } |
| |
| if (rw_opt_no_ctors) { |
| rw_note (ctors_noted++, 0, __LINE__, "Ctors test disabled."); |
| } |
| else { |
| TEST (ctors, short, std::allocator); |
| } |
| } |
| |
| if (rw_opt_no_ctors) { |
| rw_note (ctors_noted++, 0, __LINE__, "Ctors test disabled."); |
| } |
| else { |
| test_ctors (); |
| } |
| |
| return 0; |
| } |
| |
| /**************************************************************************/ |
| |
| int main (int argc, char** argv) |
| { |
| return rw_test (argc, argv, __FILE__, |
| "lib.vector.cons", |
| 0 /* no comment */, |
| run_test, |
| "|-nloops#1 " |
| "|-no-int_specializations# " |
| "|-no-short_specializations# " |
| "|-no-types# " |
| "|-no-signatures# " |
| "|-no-ctors#", |
| &rw_opt_nloops, |
| &rw_opt_no_int_spec, |
| &rw_opt_no_short_spec, |
| &rw_opt_no_types, |
| &rw_opt_no_signatures, |
| &rw_opt_no_ctors); |
| } |