UserClass operator() () /* non-const */ { // return a default-constructed UserClass intialized // to the next sequential value return UserClass (); }
// exercise vector<>::capacity() and vector<>::reserve() // focus on the complexity of the function void test_capacity (Vector::size_type nelems) { // create a vector with nelems elements Vector v (nelems); const Vector::size_type cap = v.capacity (); const Vector::size_type size = v.size (); Vector::const_pointer begin = size ? &v [0] : 0; UserClass::reset_totals (); // call reserve capacity that is less than or equal to the current value v.reserve (cap / 2); // verify that the call had no effect rw_assert (v.capacity () == cap, 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu); capacity() == %zu, " "got %zu", nelems, cap / 2, cap, v.capacity ()); if (size) { // verify that no reallocation took place rw_assert (begin == &v [0], 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu) unexpectedly " "reallocated", nelems, cap / 2); } // call reserve the same capacity as the current value v.reserve (cap); // verify that the call had no effect rw_assert (v.capacity () == cap, 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu); capacity() == %zu, " "got %zu", nelems, cap / 2, cap, v.capacity ()); if (size) { // verify that no reallocation took place rw_assert (begin == &v [0], 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu) unexpectedly " "reallocated", nelems, cap / 2); } // call reserve with a larger capacity then is available v.reserve (cap + 1); // 23.2.4.2, p2: After reserve (), capacity () is greater or equal // to the reserve value if reallocation happens rw_assert (v.capacity () >= cap + 1, 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu); capacity() > %zu, got %zu", nelems, cap + 1, cap, v.capacity ()); // 23.2.3.2, p3: reserve shall not change the size of the sequence rw_assert (v.size () == size, 0, __LINE__, "vector<UserClass>(%zu).reserve(); size() == %zu, got %zu", nelems, size, v.size ()); // 23.2.3.2, p3: takes at most linear time in the size of the sequence rw_assert (UserClass::n_total_copy_ctor_ == v.size (), 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu) complexity: " "copy ctor called %zu times when size() = %zu", nelems, cap + 1, UserClass::n_total_copy_ctor_, v.size ()); if (size) { begin = &v [0]; // verify 23.2.4.2, p5: no reallocation takes place until // the size of the container would exceed its capacity for (Vector::size_type i = 0; i != v.capacity () - size; ++i) { v.push_back (UserClass ()); rw_assert (begin == &v [0], 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu); insertion of " "element %zu unexpectedly reallocated; size() = %zu", nelems, cap + 1, v.size ()); } } if (rw_opt_no_exceptions) return; #ifndef _RWSTD_NO_EXCEPTIONS // exercise reserve exception const char *caught = 0; Vector::size_type too_much = v.max_size () + 1; if (!too_much) too_much = v.max_size (); try { v.reserve (too_much); } catch (std::length_error) { caught = ""; } catch (...) { caught = "unknown exception"; } rw_assert (0 != caught, 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu) " "expected exception not thrown", nelems, too_much); if (caught) rw_assert ('\0' == *caught, 0, __LINE__, "vector<UserClass>(%zu).reserve(%zu) " "expected length_error, got %s", nelems, too_much, caught); #endif // _RWSTD_NO_EXCEPTIONS }