Return-Path: Delivered-To: apmail-incubator-stdcxx-dev-archive@www.apache.org Received: (qmail 92001 invoked from network); 23 Jan 2006 21:57:29 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 23 Jan 2006 21:57:29 -0000 Received: (qmail 76177 invoked by uid 500); 23 Jan 2006 21:57:29 -0000 Delivered-To: apmail-incubator-stdcxx-dev-archive@incubator.apache.org Received: (qmail 76156 invoked by uid 500); 23 Jan 2006 21:57:28 -0000 Mailing-List: contact stdcxx-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-dev@incubator.apache.org Received: (qmail 76145 invoked by uid 99); 23 Jan 2006 21:57:28 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Jan 2006 13:57:28 -0800 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [12.17.213.84] (HELO bco-exchange.bco.roguewave.com) (12.17.213.84) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Jan 2006 13:57:26 -0800 Received: from [10.70.2.6] (skynet.bco.roguewave.com [10.70.2.6]) by bco-exchange.bco.roguewave.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2657.72) id ZGW28H0R; Mon, 23 Jan 2006 14:50:03 -0700 Message-ID: <43D551B6.2080304@roguewave.com> Date: Mon, 23 Jan 2006 14:59:18 -0700 From: Liviu Nicoara User-Agent: Mozilla Thunderbird 1.0.7 (X11/20050923) X-Accept-Language: en-us, en MIME-Version: 1.0 To: stdcxx-dev@incubator.apache.org Subject: Re: 23.containers.deque.modifiers.cpp References: <43CE6FAC.3000507@moscow.vdiweb.com> <43CFE7F6.4060208@roguewave.com> <43D01A83.4020206@roguewave.com> <43D5298C.2060009@roguewave.com> <43D542BD.7040305@roguewave.com> In-Reply-To: <43D542BD.7040305@roguewave.com> Content-Type: multipart/mixed; boundary="------------060604020308020402090007" X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N --------------060604020308020402090007 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit I have attached a second version of the test. Please let me know if this addresses the points you raised. Thanks, Liviu Liviu Nicoara wrote: > Martin Sebor wrote: > >>Liviu Nicoara wrote: >> >> >>>I have attached my tentative porting of lib.deque.modifiers test to the >>>new driver. Martin, I would appreciate suggestions for improving the >>>sections which use ToString class (one of those uses split formatting). >> >> >>I don't see the class defined in the test. Did you by any chance >>move/copy it into your version alg_test.h? > > > Yes, I did. My bad, I just wanted to get your feed-back on the > formatting bits and I didn't think that was important. I will stick a > ToString in each of the tests using it. > > >>I think the bits that use the ToString class are fine. As soon as >>I'm done with the extension to rw_asnprintf() to format arrays of >>class X (we need to rename it!) it should be straightforward to >>simply remove the class and pass the arrays directly to rw_assert(). > > > Super. > > >>Btw., the old tests were designed to avoid invoking the RW_ASSERT >>macro except on failure (i.e., there's usually an if (failed) { } >>block around it). > > > I got that. I will eliminate the conditionals from now on. > > Thanks, > Liviu > --------------060604020308020402090007 Content-Type: text/x-c++src; name="23.containers.deque.modifiers.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="23.containers.deque.modifiers.cpp" /*************************************************************************** * * 23.containers.deque.modifiers.cpp - test exercising [lib.deque.modifiers] * * $Id$ * *************************************************************************** * * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave * Software division. 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. * **************************************************************************/ #ifdef _MSC_VER // silence warning C4244: 'argument' : conversion from 'T' to // 'const std::allocator<_TypeT>::value_type', possible loss of data // issued for deque::assign(InputIterator a, InputIterator b) and // deque::insert(iterator, InputIterator a, InputIterator b) due // the implicit conversion of a to size_type and b to value_type // required by DR 438: // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438 # pragma warning (disable: 4244) #endif #include // for sprintf() #include // for free() #include // for strlen() #include #ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE // disabled for MSVC since it can't reliably replace the operators # define DEFINE_REPLACEMENT_NEW_AND_DELETE #endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE #include #include #include #include /**************************************************************************/ // for convenience typedef unsigned char UChar; // Formatting class template struct ToString { public: ToString (const T* first, const T* last, int pos, bool use_id = false) : buffer_ (0) { std::size_t buflen = 0; if (first > last) { rw_asnprintf (&buffer_, &buflen, "%s", "bad range"); return; } for (const T* ptr = first; ptr != last; ++ptr) { char* tmp = buffer_; // Shoddy formatting, relying on buffer_ not being modified // until it has been processed (first %s in formatting string) rw_asnprintf (&tmp, &buflen, "%s%{?}>%{;}%{?}%d:%{;}%{lc}%{?}<%{;}", buffer_ ? buffer_ : "\0", ptr - first == pos, // '>' use_id, ptr->id_, // ":" ptr->val_, // ptr - first == pos); // '<' buffer_ = tmp; } } ~ToString () { if (buffer_) std::free (buffer_); } operator const char* () const { return buffer_; } private: char* buffer_; }; /**************************************************************************/ typedef std::deque > Deque; std::size_t new_capacity; namespace __rw { _RWSTD_SPECIALIZED_FUNCTION inline Deque::size_type __rw_new_capacity(Deque::size_type n, const Deque*) { if (n) { // non-zero size argument indicates a request for an increase // in the capacity of a deque object's dynamically sizable // vector of nodes return n * 2; } // zero size argument is a request for the initial size of a deque // object's dynamically sizable vector of nodes or for the size of // the objects's fixed-size buffer for elements return new_capacity; } } /**************************************************************************/ enum { NewThrows = 0x1 /* cause operator new to throw */, CopyCtorThrows = 0x2 /* cause element's copy ctor to throw */, AssignmentThrows = 0x4 /* cause element's assignment to throw */ }; enum MemberFunction { Assign_n /* deque::assign (size_type, const_reference) */, AssignRange /* deque::assign (InputIterator, InputIterator) */, Erase_1 /* deque::erase (iterator) */, EraseRange /* deque::erase (iterator, iterator) */, Insert_1 /* deque::insert (iterator, const_reference) */, Insert_n /* deque::insert (iterator, size_type, const_reference) */, InsertRange /* deque::insert (iterator, InputIterator, InputIterator) */ }; // causes operator new, deque element's copy ctor, or assignment operator // to throw an exception and iterates as long as the member function exits // by throwing an exception; verifies that the exception had no effects // on the container template void exception_loop (int line /* line number in caller*/, MemberFunction mfun /* deque member function */, const char *fcall /* function call string */, int exceptions /* enabled exceptions */, Deque &deq /* container to call function on */, const Deque::iterator &it /* iterator into container */, int n /* number of elements or offset */, const X *x /* pointer to an element or 0 */, const Iterator &first /* beginning of range */, const Iterator &last /* end of range to insert */, int *n_copy /* number of copy ctors */, int *n_asgn /* number of assignments */) { std::size_t throw_after = 0; // get the initial size of the container and its begin() iterator // to detect illegal changes after an exception (i.e., violations // if the strong exception guarantee) const std::size_t size = deq.size (); const Deque::const_iterator begin = deq.begin (); const Deque::const_iterator end = deq.end (); #ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE rwt_free_store* const pst = rwt_get_free_store (0); #endif // DEFINE_REPLACEMENT_NEW_AND_DELETE // repeatedly call the specified member function until it returns // without throwing an exception for ( ; ; ) { // detect objects constructed but not destroyed after an exception std::size_t x_count = X::count_; _RWSTD_ASSERT (n_copy); _RWSTD_ASSERT (n_asgn); *n_copy = X::n_total_copy_ctor_; *n_asgn = X::n_total_op_assign_; #ifndef _RWSTD_NO_EXCEPTIONS // iterate for `n=throw_after' starting at the next call to operator // new, forcing each call to throw an exception, until the insertion // finally succeeds (i.e, no exception is thrown) # ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE if (exceptions & NewThrows) { *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1; } # endif // DEFINE_REPLACEMENT_NEW_AND_DELETE if (exceptions & CopyCtorThrows) { X::copy_ctor_throw_count_ = X::n_total_copy_ctor_ + throw_after; } if (exceptions & AssignmentThrows) { X::op_assign_throw_count_ = X::n_total_op_assign_ + throw_after; } #endif // _RWSTD_NO_EXCEPTIONS _TRY { switch (mfun) { case Assign_n: _RWSTD_ASSERT (x); deq.assign (n, *x); break; case AssignRange: deq.assign (first, last); break; case Erase_1: deq.erase (it); break; case EraseRange: { const Deque::iterator erase_end (it + n); deq.erase (it, erase_end); break; } case Insert_1: _RWSTD_ASSERT (x); deq.insert (it, *x); break; case Insert_n: _RWSTD_ASSERT (x); deq.insert (it, n, *x); break; case InsertRange: deq.insert (it, first, last); break; } } _CATCH (...) { // verify that an exception thrown from the member function // didn't cause a change in the state of the container rw_assert (deq.size () == size, 0, line, "line %d: %s: size unexpectedly changed " "from %u to %u after an exception", __LINE__, fcall, size, deq.size ()); rw_assert (deq.begin () == begin, 0, line, "line %d: %s: begin() unexpectedly " "changed after an exception by %d", __LINE__, fcall, deq.begin () - begin); rw_assert (deq.end () == end, 0, line, "line %d: %s: end() unexpectedly " "changed after an exception by %d", __LINE__, fcall, deq.end () - end); // count the number of objects to detect leaks x_count = X::count_ - x_count; rw_assert (x_count == deq.size () - size, 0, line, "line %d: %s: leaked %d objects " "after an exception", __LINE__, fcall, x_count - (deq.size () - size)); if (exceptions) { // increment to allow this call to operator new to succeed // and force the next one to fail, and try to insert again ++throw_after; } else break; continue; } // count the number of objects to detect leaks x_count = X::count_ - x_count; rw_assert (x_count == deq.size () - size, 0, line, "line %d: %s: leaked %d objects " "after a successful insertion", __LINE__, fcall, x_count - (deq.size () - size)); break; } #ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE // disable exceptions from replacement operator new *pst->throw_at_calls_ [0] = _RWSTD_SIZE_MAX; #endif // DEFINE_REPLACEMENT_NEW_AND_DELETE X::copy_ctor_throw_count_ = 0; X::op_assign_throw_count_ = 0; // compute the number of calls to X copy ctor and assignment operator // and set `n_copy' and `n_assgn' to the value of the result *n_copy = X::n_total_copy_ctor_ - *n_copy; *n_asgn = X::n_total_op_assign_ - *n_asgn; } // used to determine whether insert() can or cannot use // an algorithm optimized for BidirectionalIterators bool is_bidirectional (std::input_iterator_tag) { return false; } bool is_bidirectional (std::bidirectional_iterator_tag) { return true; } // returns the number of invocations of the assignment operators // for a call to deque::insert(iterator, InputIterator, InputIterator) // (the value depends on the iterator category) template std::size_t insert_assignments (Iterator it, int nelems, std::size_t off, std::size_t seqlen, std::size_t inslen) { if (is_bidirectional (_RWSTD_ITERATOR_CATEGORY (Iterator, it))) return 0 == nelems ? 0 : off < seqlen - off ? off : seqlen - off; if (0 < nelems) --nelems; if (0 == nelems || 0 == inslen) return 0; // compute the number of assignments done // to insert the first element in the sequence const std::size_t first = off < seqlen - off ? off : seqlen - off; // recursively compute the numner of assignments // for the rest of the elements in the sequence const std::size_t rest = insert_assignments (it, nelems, off + 1, seqlen + 1, inslen - 1); return first + rest; } template int test_insert (int line, int exceptions, const Iterator &dummy, int nelems, const char *seq, std::size_t seqlen, std::size_t off, const char *ins, std::size_t inslen, const char *res, std::size_t reslen) { int nfailed = 0; const X* const xseq = X::from_char (seq, seqlen); X* const xins = X::from_char (ins, inslen); Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque (); // offset must be valid _RWSTD_ASSERT (off <= deq.size ()); const Deque::iterator iter = deq.begin () + off; // only insert() at either end of the container is exception safe // insertions into the middle of the container are not (i.e., the // container may grow or may even become inconsistent) if (off && off < deq.size ()) exceptions = 0; // Format arrayS of X's ToString seqstr (xseq, xseq + seqlen, -1); ToString insstr (xins, xins + inslen, -1); // format a string describing the function call being exercised // (used in diagnostic output below) char* buffer = 0; std::size_t len = 0; rw_asnprintf (&buffer, &len, "deque(%s).insert(" "%{?}begin(), %{;}%{?}end (), %{:}begin () + %zd%{;}%{;}" "%{?}%d)%{:}%{?}%s)%{:}%d, %d)%{;}%{;}", (const char*)seqstr, 0 == off, seqlen == off, off, nelems == -2, *ins, nelems == -1, (const char*)insstr, nelems, *ins); int n_copy = X::n_total_copy_ctor_; int n_asgn = X::n_total_op_assign_; if (-2 == nelems) { // insert(iterator, const_reference) exception_loop (line, Insert_1, buffer, exceptions, deq, iter, nelems, xins, dummy, dummy, &n_copy, &n_asgn); } else if (-1 == nelems) { // insert(iterator, Iterator, Iterator) if (inslen > 1) exceptions = 0; const Iterator first = make_iter (xins, xins, xins + inslen, dummy); const Iterator last = make_iter (xins + inslen, xins, xins + inslen, dummy); exception_loop (line, InsertRange, buffer, exceptions, deq, iter, nelems, 0, first, last, &n_copy, &n_asgn); } else { // insert(iterator, size_type, const_reference) if (nelems > 1) exceptions = 0; exception_loop (line, Insert_n, buffer, exceptions, deq, iter, nelems, xins, dummy, dummy, &n_copy, &n_asgn); } // verify the expected size of the deque after insertion rw_assert (deq.size () == reslen || ++nfailed == 0, __FILE__, line, "line %d: %s: size == %u, got %u\n", __LINE__, buffer, reslen, deq.size ()); // verify the expected contents of the deque after insertion const Deque::const_iterator resbeg = deq.begin (); const Deque::const_iterator resend = deq.end (); for (Deque::const_iterator it = resbeg; it != resend; ++it) { if ((*it).val_ != UChar (res [it - resbeg])) { char* const got = new char [deq.size () + 1]; for (Deque::const_iterator i = resbeg; i != resend; ++i) { got [i - resbeg] = char ((*i).val_); } got [deq.size ()] = '\0'; ++nfailed; rw_assert (false, __FILE__, line, "line %d: %s: expected %s, got %s\n", __LINE__, buffer, res, got); delete[] got; break; } } // verify the complexity of the operation in terms of the number // of calls to the copy ctor and assignment operator on value_type const std::size_t expect_copy = nelems < 0 ? inslen : nelems; rw_assert (n_copy == int (expect_copy) || ++nfailed == 0, __FILE__, line, "line %d: %s: expected %u invocations " "of X::X(const X&), got %d\n", __LINE__, buffer, expect_copy, n_copy); // compute the number of calls to the assignment operator const std::size_t expect_asgn = insert_assignments (dummy, nelems, off, seqlen, inslen); rw_assert (n_asgn == int (expect_asgn) || ++nfailed == 0, __FILE__, line, "line %d: %s: expected %u invocations " "of X::operator=(const X&), got %d\n", __LINE__, buffer, expect_asgn, n_asgn); // Free buffer storage std::free (buffer); delete[] xins; delete[] xseq; return 0 != nfailed; } /**************************************************************************/ template void test_insert_range (const Iterator &it, const char* itname) { rw_info (0, 0 ,0, "std::deque::insert(iterator, %s, %s)", itname, itname); static int nfailed; #undef TEST #define TEST(seq, off, ins, res) \ nfailed += test_insert (__LINE__, -1, \ it, -1, \ seq, sizeof seq - 1, \ std::size_t (off), \ ins, sizeof ins - 1, \ res, sizeof res - 1) // +---------------------------------------- seq // | +--------------------------------- off // | | +----------------------------- ins // | | | +---------------------- res // | | | | // v v v v TEST ("", +0, "", ""); TEST ("", +0, "a", "a"); TEST ("", +0, "ab", "ab"); TEST ("", +0, "abc", "abc"); TEST ("a", +0, "", "a"); TEST ("b", +0, "a", "ab"); TEST ("c", +0, "ab", "abc"); TEST ("cd", +0, "ab", "abcd"); TEST ("def", +0, "abc", "abcdef"); TEST ("a", +1, "", "a"); TEST ("a", +1, "b", "ab"); TEST ("a", +1, "bc", "abc"); TEST ("a", +1, "bcd", "abcd"); TEST ("ab", +1, "", "ab"); TEST ("ac", +1, "b", "abc"); TEST ("acd", +1, "b", "abcd"); TEST ("ab", +2, "", "ab"); TEST ("ab", +2, "c", "abc"); TEST ("ab", +2, "cd", "abcd"); TEST ("abc", +2, "", "abc"); TEST ("abd", +2, "c", "abcd"); TEST ("abe", +2, "cd", "abcde"); TEST ("abf", +2, "cde", "abcdef"); TEST ("abc", +3, "", "abc"); TEST ("abc", +3, "d", "abcd"); TEST ("abc", +3, "de", "abcde"); TEST ("abc", +3, "def", "abcdef"); #define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define LOWER "abcdefghijklmnopqrstuvwxyz" TEST (UPPER, +0, LOWER, "" LOWER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +1, LOWER, "A" LOWER "BCDEFGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +2, LOWER, "AB" LOWER "CDEFGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +3, LOWER, "ABC" LOWER "DEFGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +4, LOWER, "ABCD" LOWER "EFGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +5, LOWER, "ABCDE" LOWER "FGHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +6, LOWER, "ABCDEF" LOWER "GHIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +7, LOWER, "ABCDEFG" LOWER "HIJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +8, LOWER, "ABCDEFGH" LOWER "IJKLMNOPQRSTUVWXYZ"); TEST (UPPER, +9, LOWER, "ABCDEFGHI" LOWER "JKLMNOPQRSTUVWXYZ"); TEST (UPPER, +10, LOWER, "ABCDEFGHIJ" LOWER "KLMNOPQRSTUVWXYZ"); TEST (UPPER, +11, LOWER, "ABCDEFGHIJK" LOWER "LMNOPQRSTUVWXYZ"); TEST (UPPER, +12, LOWER, "ABCDEFGHIJKL" LOWER "MNOPQRSTUVWXYZ"); TEST (UPPER, +13, LOWER, "ABCDEFGHIJKLM" LOWER "NOPQRSTUVWXYZ"); TEST (UPPER, +14, LOWER, "ABCDEFGHIJKLMN" LOWER "OPQRSTUVWXYZ"); TEST (UPPER, +15, LOWER, "ABCDEFGHIJKLMNO" LOWER "PQRSTUVWXYZ"); TEST (UPPER, +16, LOWER, "ABCDEFGHIJKLMNOP" LOWER "QRSTUVWXYZ"); TEST (UPPER, +17, LOWER, "ABCDEFGHIJKLMNOPQ" LOWER "RSTUVWXYZ"); TEST (UPPER, +18, LOWER, "ABCDEFGHIJKLMNOPQR" LOWER "STUVWXYZ"); TEST (UPPER, +19, LOWER, "ABCDEFGHIJKLMNOPQRS" LOWER "TUVWXYZ"); TEST (UPPER, +20, LOWER, "ABCDEFGHIJKLMNOPQRST" LOWER "UVWXYZ"); TEST (UPPER, +21, LOWER, "ABCDEFGHIJKLMNOPQRSTU" LOWER "VWXYZ"); TEST (UPPER, +22, LOWER, "ABCDEFGHIJKLMNOPQRSTUV" LOWER "WXYZ"); TEST (UPPER, +23, LOWER, "ABCDEFGHIJKLMNOPQRSTUVW" LOWER "XYZ"); TEST (UPPER, +24, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWX" LOWER "YZ"); TEST (UPPER, +25, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXY" LOWER "Z"); TEST (UPPER, +26, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" LOWER ""); if (!nfailed) rw_assert (true, 0, __LINE__, ""); } /**************************************************************************/ template void test_insert_int_range (const T&, const IntType&, const char* t_name, const char* int_name) { rw_info (0, 0, 0, "std::deque<%s>::insert(iterator, %s, %s)", t_name, int_name, int_name); std::deque d; typename std::deque::iterator it = d.begin (); // deque::insert(iterator, size_type, const_reference) d.insert (it, IntType (1), IntType (0)); rw_assert (1 == d.size (), 0, __LINE__, "deque<%s>::insert(begin(), %s = 1, %s = 0); size() == 1," " got %u", t_name, int_name, int_name, d.size ()); it = d.begin (); ++it; d.insert (it, IntType (3), IntType (2)); rw_assert (4 == d.size (), 0, __LINE__, "deque<%s>::insert(begin() + 1, %s = 3, %s = 2); size() == 4," " got %u", t_name, int_name, int_name, d.size ()); it = d.begin (); ++it; d.insert (it, IntType (2), IntType (1)); rw_assert (6 == d.size (), 0, __LINE__, "deque<%s>::insert(begin() + 1, %s = 2, %s = 1); size() == 6," " got %u", t_name, int_name, int_name, d.size ()); } template void test_insert_int_range (const T &dummy, const char* tname) { test_insert_int_range (dummy, (signed char)0, tname, "signed char"); test_insert_int_range (dummy, (unsigned char)0, tname, "unsigned char"); test_insert_int_range (dummy, short (), tname, "short"); test_insert_int_range (dummy, (unsigned short)0, tname, "unsigned short"); test_insert_int_range (dummy, int (), tname, "int"); test_insert_int_range (dummy, (unsigned int)0, tname, "unsigned int"); test_insert_int_range (dummy, long (), tname, "long"); test_insert_int_range (dummy, (unsigned long)0, tname, "unsigned long"); #ifdef _RWSTD_LONG_LONG test_insert_int_range (dummy, (_RWSTD_LONG_LONG)0, tname, "long long"); test_insert_int_range (dummy, (unsigned _RWSTD_LONG_LONG)0, tname, "unsigned long long"); #endif // _RWSTD_LONG_LONG } /**************************************************************************/ void test_insert () { ////////////////////////////////////////////////////////////////// // exercise deque::insert(iterator, const_reference) rw_info (0, 0, 0, "std::deque::insert(iterator, const_reference)"); int nfailed = 0; #undef TEST #define TEST(seq, off, ins, res) do { \ const char insseq [] = { ins, '\0' }; \ nfailed += test_insert (__LINE__, -1, \ (X*)0, -2, \ seq, sizeof seq - 1, \ std::size_t (off), \ insseq, 1, \ res, sizeof res - 1); \ } while (0) // +------------------- original sequence // | +----------- insertion offset // | | +------ element to insert // | | | +-- resulting sequence // | | | | // V V V V TEST ("", +0, 'a', "a"); TEST ("b", +0, 'a', "ab"); TEST ("bc", +0, 'a', "abc"); TEST ("bcd", +0, 'a', "abcd"); TEST ("bcde", +0, 'a', "abcde"); TEST ("a", +1, 'b', "ab"); TEST ("ac", +1, 'b', "abc"); TEST ("acd", +1, 'b', "abcd"); TEST ("acde", +1, 'b', "abcde"); TEST ("ab", +2, 'c', "abc"); TEST ("abd", +2, 'c', "abcd"); TEST ("abde", +2, 'c', "abcde"); TEST ("abc", +3, 'd', "abcd"); TEST ("abce", +3, 'd', "abcde"); TEST ("abcd", +4, 'e', "abcde"); #define A_to_B "AB" #define A_to_C "ABC" #define A_to_D "ABCD" #define A_to_E "ABCDE" #define A_to_F "ABCDEF" #define A_to_G "ABCDEFG" #define A_to_H "ABCDEFGH" #define A_to_I "ABCDEFGHI" #define A_to_J "ABCDEFGHIJ" #define A_to_K "ABCDEFGHIJK" #define A_to_L "ABCDEFGHIJKL" #define A_to_M "ABCDEFGHIJKLM" #define A_to_N "ABCDEFGHIJKLMN" #define A_to_O "ABCDEFGHIJKLMNO" #define A_to_P "ABCDEFGHIJKLMNOP" #define A_to_Q "ABCDEFGHIJKLMNOPQ" #define A_to_R "ABCDEFGHIJKLMNOPQR" #define A_to_S "ABCDEFGHIJKLMNOPQRS" #define A_to_T "ABCDEFGHIJKLMNOPQRST" #define A_to_U "ABCDEFGHIJKLMNOPQRSTU" #define A_to_V "ABCDEFGHIJKLMNOPQRSTUV" #define A_to_W "ABCDEFGHIJKLMNOPQRSTUVW" #define A_to_X "ABCDEFGHIJKLMNOPQRSTUVWX" #define A_to_Y "ABCDEFGHIJKLMNOPQRSTUVWXY" #define A_to_Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define B_to_Z "BCDEFGHIJKLMNOPQRSTUVWXYZ" #define C_to_Z "CDEFGHIJKLMNOPQRSTUVWXYZ" #define D_to_Z "DEFGHIJKLMNOPQRSTUVWXYZ" #define E_to_Z "EFGHIJKLMNOPQRSTUVWXYZ" #define F_to_Z "FGHIJKLMNOPQRSTUVWXYZ" #define G_to_Z "GHIJKLMNOPQRSTUVWXYZ" #define H_to_Z "HIJKLMNOPQRSTUVWXYZ" #define I_to_Z "IJKLMNOPQRSTUVWXYZ" #define J_to_Z "JKLMNOPQRSTUVWXYZ" #define K_to_Z "KLMNOPQRSTUVWXYZ" #define L_to_Z "LMNOPQRSTUVWXYZ" #define M_to_Z "MNOPQRSTUVWXYZ" #define N_to_Z "NOPQRSTUVWXYZ" #define O_to_Z "OPQRSTUVWXYZ" #define P_to_Z "PQRSTUVWXYZ" #define Q_to_Z "QRSTUVWXYZ" #define R_to_Z "RSTUVWXYZ" #define S_to_Z "STUVWXYZ" #define T_to_Z "TUVWXYZ" #define U_to_Z "UVWXYZ" #define V_to_Z "VWXYZ" #define W_to_Z "WXYZ" #define X_to_Z "XYZ" #define Y_to_Z "YZ" TEST (A_to_Z, + 0, '^', "" "^" A_to_Z); TEST (A_to_Z, + 1, '^', "A" "^" B_to_Z); TEST (A_to_Z, + 2, '^', A_to_B "^" C_to_Z); TEST (A_to_Z, + 3, '^', A_to_C "^" D_to_Z); TEST (A_to_Z, + 4, '^', A_to_D "^" E_to_Z); TEST (A_to_Z, + 5, '^', A_to_E "^" F_to_Z); TEST (A_to_Z, + 6, '^', A_to_F "^" G_to_Z); TEST (A_to_Z, + 7, '^', A_to_G "^" H_to_Z); TEST (A_to_Z, + 8, '^', A_to_H "^" I_to_Z); TEST (A_to_Z, + 9, '^', A_to_I "^" J_to_Z); TEST (A_to_Z, +10, '^', A_to_J "^" K_to_Z); TEST (A_to_Z, +11, '^', A_to_K "^" L_to_Z); TEST (A_to_Z, +12, '^', A_to_L "^" M_to_Z); TEST (A_to_Z, +13, '^', A_to_M "^" N_to_Z); TEST (A_to_Z, +14, '^', A_to_N "^" O_to_Z); TEST (A_to_Z, +15, '^', A_to_O "^" P_to_Z); TEST (A_to_Z, +16, '^', A_to_P "^" Q_to_Z); TEST (A_to_Z, +17, '^', A_to_Q "^" R_to_Z); TEST (A_to_Z, +18, '^', A_to_R "^" S_to_Z); TEST (A_to_Z, +19, '^', A_to_S "^" T_to_Z); TEST (A_to_Z, +20, '^', A_to_T "^" U_to_Z); TEST (A_to_Z, +21, '^', A_to_U "^" V_to_Z); TEST (A_to_Z, +22, '^', A_to_V "^" W_to_Z); TEST (A_to_Z, +23, '^', A_to_W "^" X_to_Z); TEST (A_to_Z, +24, '^', A_to_X "^" Y_to_Z); TEST (A_to_Z, +25, '^', A_to_Y "^" "Z"); TEST (A_to_Z, +26, '^', A_to_Z "^" ""); if (!nfailed) rw_assert (true, 0, __LINE__, ("")); ////////////////////////////////////////////////////////////////// // exercise deque::insert(iterator, size_type, const_reference) rw_info (0, 0, 0, "std::deque::insert(iterator, size_type, " "const_reference)"); nfailed = 0; #undef TEST #define TEST(seq, off, n, ins, res) do { \ const char insseq [] = { ins, '\0' }; \ nfailed += test_insert (__LINE__, -1, \ (X*)0, n, \ seq, sizeof seq - 1, \ std::size_t (off), \ insseq, 1, \ res, sizeof res - 1); \ } while (0) TEST ("", +0, 0, 'a', ""); TEST ("", +0, 1, 'a', "a"); TEST ("", +0, 2, 'b', "bb"); TEST ("", +0, 3, 'c', "ccc"); TEST ("a", +0, 0, 'a', "a"); TEST ("b", +0, 1, 'a', "ab"); TEST ("b", +0, 2, 'a', "aab"); TEST ("b", +0, 3, 'a', "aaab"); TEST ("ab", +1, 0, 'b', "ab"); TEST ("ac", +1, 1, 'b', "abc"); TEST ("ac", +1, 2, 'b', "abbc"); TEST ("ac", +1, 3, 'b', "abbbc"); TEST ("abcd", +2, 0, 'c', "abcd"); TEST ("abde", +2, 1, 'c', "abcde"); TEST ("abde", +2, 2, 'c', "abccde"); TEST ("abde", +2, 3, 'c', "abcccde"); if (!nfailed) rw_assert (true, 0, __LINE__, ("")); ////////////////////////////////////////////////////////////////// // exercise deque::insert(iterator, InputIterator, InputIterator) rw_info (0, 0, 0, "template std::deque::" "insert(iterator, InputIterator, InputIterator)"); test_insert_range (InputIter(0, 0, 0), "InputIter"); test_insert_range (FwdIter(), "FwdIter"); test_insert_range (BidirIter(), "BidirIter"); test_insert_range (RandomAccessIter(), "RandomAccessIter"); ////////////////////////////////////////////////////////////////// // exercise deque::insert(iterator, int, int) rw_info (0, 0, 0, "template " "std::deque::" "insert(iterator, IntType, IntType)"); test_insert_int_range ((signed char)0, "signed char"); test_insert_int_range ((unsigned char)0, "unsigned char"); test_insert_int_range (short (), "short"); test_insert_int_range ((unsigned short)0, "unsigned short"); test_insert_int_range (int (), "int"); test_insert_int_range ((unsigned int)0, "unsigned int"); test_insert_int_range (long (), "long"); test_insert_int_range ((unsigned long)0, "unsigned long"); #ifdef _RWSTD_LONG_LONG test_insert_int_range ((_RWSTD_LONG_LONG)0, "long long"); test_insert_int_range ((unsigned _RWSTD_LONG_LONG)0, "unsigned long long"); #endif // _RWSTD_LONG_LONG } /**************************************************************************/ template int test_assign (int line, int exceptions, const Iterator &dummy, int nelems, const char *seq, std::size_t seqlen, const char *asn, std::size_t asnlen, const char *res, std::size_t reslen) { int nfailed = 0; const X* const xseq = X::from_char (seq, seqlen); X* const xasn = X::from_char (asn, asnlen); Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque (); // Format array of X ToString seqstr (xseq, xseq + seqlen, -1); ToString asnstr (xasn, xasn + asnlen, -1); // format a string describing the function call being exercised // (used in diagnostic output below) char* buffer = 0; std::size_t len = 0; rw_asnprintf (&buffer, &len, "deque(%s).assign(" "%{?}%s)%{:}%d, %d)%{;}", (const char*)seqstr, nelems < 0, (const char*)asnstr, nelems, *asn); int n_copy = X::n_total_copy_ctor_; int n_asgn = X::n_total_op_assign_; // create a dummy deque iterator to pass to exception_loop // (the object will not be used by the functiuon) const Deque::iterator dummy_it = deq.begin (); if (nelems < 0) { // assign(Iterator, Iterator) if (asnlen > 1) exceptions = 0; const Iterator first = make_iter (xasn, xasn, xasn + asnlen, dummy); const Iterator last = make_iter (xasn + asnlen, xasn, xasn + asnlen, dummy); exception_loop (line, AssignRange, buffer, exceptions, deq, dummy_it, nelems, 0, first, last, &n_copy, &n_asgn); } else { // assign(size_type, const_reference) if (nelems > 1) exceptions = 0; exception_loop (line, Assign_n, buffer, exceptions, deq, dummy_it, nelems, xasn, dummy, dummy, &n_copy, &n_asgn); } // verify the expected size of the deque after assignment rw_assert (deq.size () == reslen || ++nfailed == 0, 0, line, "line %d: %s: size == %u, got %u\n", __LINE__, buffer, reslen, deq.size ()); // verify the expected contents of the deque after assignment const Deque::const_iterator resbeg = deq.begin (); const Deque::const_iterator resend = deq.end (); for (Deque::const_iterator it = resbeg; it != resend; ++it) { const Deque::size_type inx = it - resbeg; _RWSTD_ASSERT (inx < deq.size ()); if ((*it).val_ != UChar (res [inx])) { char* const got = new char [deq.size () + 1]; for (Deque::const_iterator i = resbeg; i != resend; ++i) { const Deque::size_type inx_2 = i - resbeg; _RWSTD_ASSERT (inx_2 < deq.size ()); got [inx_2] = char ((*i).val_); } got [deq.size ()] = '\0'; ++nfailed; rw_assert (false, 0, line, "line %d: %s: expected %s, got %s\n", __LINE__, buffer, res, got); delete[] got; break; } } // set asnlen to the number of elements assigned to the container if (0 <= nelems) asnlen = std::size_t (nelems); // verify the complexity of the operation in terms of the number // of calls to the copy ctor and assignment operator on value_type // the number of invocations of the copy ctor and the assignment // operator depends on whether the implementation of assign() // strictly follows the requirements in 23.2.1.1, p7 or p8 and // destroys the existing elements before inserting the new ones, // or whether it assigns the new elements over the existing ones #ifndef _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE const std::size_t expect_copy = seqlen < asnlen ? asnlen - seqlen : 0; const std::size_t expect_asgn = asnlen < seqlen ? asnlen : seqlen; #else // if defined (_RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE) const std::size_t expect_copy = asnlen; const std::size_t expect_asgn = 0; #endif // _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE rw_assert (n_copy == int (expect_copy) || ++nfailed == 0, 0, line, "line %d: %s: expected %u invocations " "of X::X(const X&), got %d\n", __LINE__, buffer, expect_copy, n_copy); rw_assert (n_asgn == int (expect_asgn) || ++nfailed == 0, 0, line, "line %d: %s: expected %u invocations " "of X::operator=(const X&), got %d\n", __LINE__, buffer, expect_asgn, n_asgn); // Free buffer storage std::free (buffer); delete[] xasn; delete[] xseq; return 0 != nfailed; } template void test_assign_range (const Iterator &it, const char* itname) { rw_info (0, 0, 0, "std::deque::assign(%s, %s)", itname, itname); static int nfailed; static const char seq[] = "abcdefghijklmnopqrstuvwxyz"; static const char asn[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for (std::size_t i = 0; i != sizeof seq - 1; ++i) { for (std::size_t j = 0; j != sizeof asn - 1; ++j) { nfailed += test_assign (__LINE__, 0, it, -1, seq, i, asn, j, asn, j); } } if (!nfailed) rw_assert (true, 0, __LINE__, " "); } void test_assign () { int nfailed = 0; ////////////////////////////////////////////////////////////////// // exercise // deque::assign(size_type, const_reference) rw_info (0, 0, 0, "std::deque::assign(size_type, const_reference)"); static const char seq[] = "abcdefghijklmnopqrstuvwxyz"; static const char res[] = "AAAAAAAAAAAAAAAAAAAAAAAAAA"; for (std::size_t i = 0; i != sizeof seq - 1; ++i) { for (std::size_t j = 0; j != sizeof seq - 1; ++j) { nfailed += test_assign (__LINE__, -1, (X*)0, int (j), seq, i, res, 1U, res, j); } } if (!nfailed) rw_assert (true, 0, __LINE__, " "); ////////////////////////////////////////////////////////////////// // exercise // template // deque::assign(InputIterator, InputIterator) rw_info (0, 0, 0, "template " "std::deque::assign(InputIterator, InputIterator)"); test_assign_range (InputIter(0, 0, 0), "InputIter"); test_assign_range (FwdIter(), "FwdIter"); test_assign_range (BidirIter(), "BidirIter"); test_assign_range (RandomAccessIter(), "RandomAccessIter"); } /**************************************************************************/ int test_erase (int line, const char *seq, std::size_t seqlen, std::size_t begoff, std::size_t len, const char *res, std::size_t reslen) { int nfailed = 0; const X* const xseq = X::from_char (seq, seqlen); Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque (); const Deque::iterator start = deq.begin () + begoff; // Format array of X ToString seqstr (xseq, xseq + seqlen, -1); // Format a string describing the function call being exercised // (used in diagnostic output below); use a large enough buffer // because we cannot format in one single shot. char buffer [1024U]; rw_snprintfa (buffer, 1024U, "deque(%s).erase(%{?}end()%{:}" "%{?}begin () + %zu%{:}begin ()%{;}%{;}", (const char*)seqstr, begoff == deq.size (), begoff, begoff); int n_copy = X::n_total_copy_ctor_; int n_asgn = X::n_total_op_assign_; if (std::size_t (-1) == len) { // erase(iterator) exception_loop (line, Erase_1, buffer, 0, deq, start, 1, 0, (X*)0, (X*)0, &n_copy, &n_asgn); } else { // assign(size_type, const_reference) const Deque::iterator end = start + len; rw_snprintfa (buffer + std::strlen (buffer), 1024U - std::strlen (buffer), "%{?})%{:}%{?}, end ())%{:}%{?}, begin ())" "%{:}begin () + %zi%{;}%{;}%{;}", std::size_t (-1) == len, end == deq.end (), end == deq.begin (), end - deq.begin ()); exception_loop (line, EraseRange, buffer, 0, deq, start, len, 0, (X*)0, (X*)0, &n_copy, &n_asgn); } // verify the expected size of the deque after erasure rw_assert (deq.size () == reslen || ++nfailed == 0, 0, line, "line %d: %s: size == %u, got %u\n", __LINE__, buffer, reslen, deq.size ()); // verify the expected contents of the deque after assignment const Deque::const_iterator resbeg = deq.begin (); const Deque::const_iterator resend = deq.end (); for (Deque::const_iterator it = resbeg; it != resend; ++it) { if ((*it).val_ != UChar (res [it - resbeg])) { char* const got = new char [deq.size () + 1]; for (Deque::const_iterator i = resbeg; i != resend; ++i) { got [i - resbeg] = char ((*i).val_); } got [deq.size ()] = '\0'; ++nfailed; rw_assert (false, 0, line, "line %d: %s: expected %s, got %s\n", __LINE__, buffer, res, got); delete[] got; break; } } #if 0 // set asnlen to the number of elements assigned to the container if (0 <= nelems) asnlen = std::size_t (nelems); // verify the complexity of the operation in terms of the number // of calls to the copy ctor and assignment operator on value_type // the number of invocations of the copy ctor and the assignment // operator depends on whether the implementation of assign() // strictly follows the requirements in 23.2.1.1, p7 or p8 and // destroys the existing elements before inserting the new ones, // or whether it assigns the new elements over the existing ones #ifndef _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE const std::size_t expect_copy = seqlen < asnlen ? asnlen - seqlen : 0; const std::size_t expect_asgn = asnlen < seqlen ? asnlen : seqlen; #else // if defined (_RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE) const std::size_t expect_copy = asnlen; const std::size_t expect_asgn = 0; #endif // _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE rw_assert (n_copy == int (expect_copy) || ++nfailed == 0, 0, line, "line %d: %s: expected %u invocations " "of X::X(const X&), got %d\n", __LINE__, buffer, expect_copy, n_copy); rw_assert (n_asgn == int (expect_asgn) || ++nfailed == 0, 0, line, "line %d: %s: expected %u invocations " "of X::operator=(const X&), got %d\n", __LINE__, buffer, expect_asgn, n_asgn); #endif delete[] xseq; return 0 != nfailed; } void test_erase () { int nfailed = 0; ////////////////////////////////////////////////////////////////// // exercise deque::erase(iterator) rw_info (0, 0, 0, "std::deque::erase(iterator)"); #undef TEST #define TEST(seq, off, res) do { \ nfailed += test_erase (__LINE__, \ seq, sizeof seq - 1, \ std::size_t (off), \ std::size_t (-1), \ res, sizeof res - 1); \ } while (0) TEST ("a", 0, ""); TEST ("ab", 0, "b"); TEST ("ab", 1, "a"); TEST ("abc", 0, "bc"); TEST ("abc", 1, "ac"); TEST ("abc", 2, "ab"); TEST ("abcd", 0, "bcd"); TEST ("abcd", 1, "acd"); TEST ("abcd", 2, "abd"); TEST ("abcd", 3, "abc"); TEST ("abcde", 0, "bcde"); TEST ("abcde", 1, "acde"); TEST ("abcde", 2, "abde"); TEST ("abcde", 3, "abce"); TEST ("abcde", 4, "abcd"); TEST ("abcdef", 0, "bcdef"); TEST ("abcdef", 1, "acdef"); TEST ("abcdef", 2, "abdef"); TEST ("abcdef", 3, "abcef"); TEST ("abcdef", 4, "abcdf"); TEST ("abcdef", 5, "abcde"); TEST ("abcdefg", 0, "bcdefg"); TEST ("abcdefg", 1, "acdefg"); TEST ("abcdefg", 2, "abdefg"); TEST ("abcdefg", 3, "abcefg"); TEST ("abcdefg", 4, "abcdfg"); TEST ("abcdefg", 5, "abcdeg"); TEST ("abcdefg", 6, "abcdef"); TEST ("abcdefgh", 0, "bcdefgh"); TEST ("abcdefgh", 1, "acdefgh"); TEST ("abcdefgh", 2, "abdefgh"); TEST ("abcdefgh", 3, "abcefgh"); TEST ("abcdefgh", 4, "abcdfgh"); TEST ("abcdefgh", 5, "abcdegh"); TEST ("abcdefgh", 6, "abcdefh"); TEST ("abcdefgh", 7, "abcdefg"); ////////////////////////////////////////////////////////////////// // exercise deque::erase(iterator, iterator) rw_info (0, 0, 0, "std::deque::erase(iterator, iterator)"); } /**************************************************************************/ #ifndef _RWSTD_NO_INLINE_MEMBER_TEMPLATES # ifndef _RWSTD_NO_EXPLICIT # if !defined (_MSC_VER) || _MSC_VER > 1200 struct DR_438 { static bool cast_used; DR_438 () { } explicit DR_438 (std::size_t) { cast_used = true; } template DR_438 (T) { } }; bool DR_438::cast_used; # else // if MSVC <= 6.0 // avoid an MSVC 6.0 ICE on this code # define NO_DR_438_TEST "this version of MSVC is too broken" # endif // !MSVC || MSVC > 6.0 # else # define NO_DR_438_TEST "_RWSTD_NO_EXPLICIT #defined" # endif // _RWSTD_NO_EXPLICIT # else # define NO_DR_438_TEST "_RWSTD_NO_INLINE_MEMBER_TEMPLATES #defined" #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES void test_dr_438 () { ////////////////////////////////////////////////////////////////// // exercise the resolution of DR 438: ////////////////////////////////////////////////////////////////// // // For every sequence defined in clause [lib.containers] // and in clause [lib.strings]: // * If the constructor // // template // X (InputIterator f, InputIterator l, // const allocator_type& a = allocator_type()) // // is called with a type InputIterator that does not qualify // as an input iterator, then the constructor will behave // as if the overloaded constructor: // // X (size_type, const value_type& = value_type(), // const allocator_type& = allocator_type()) // // were called instead, with the arguments static_cast(f), // l and a, respectively. // // * If the member functions of the forms: // // template // such as insert() // rt fx1(iterator p, InputIterator f, InputIterator l); // // template // such as append(), assign() // rt fx2(InputIterator f, InputIterator l); // // template // such as replace() // rt fx3(iterator i1, iterator i2, InputIterator f, InputIterator l); // // are called with a type InputIterator that does not qualify // as an input iterator, then these functions will behave // as if the overloaded member functions: // // rt fx1(iterator, size_type, const value_type&); // // rt fx2(size_type, const value_type&); // // rt fx3(iterator, iterator, size_type, const value_type&); // // were called instead, with the same arguments. // // In the previous paragraph the alternative binding will fail // if f is not implicitly convertible to X::size_type or // if l is not implicitly convertible to X::value_type. // // The extent to which an implementation determines that a type // cannot be an input iterator is unspecified, except that // as a minimum integral types shall not qualify as input iterators. ////////////////////////////////////////////////////////////////// rw_info (0, 0, 0, "resolution of DR 438"); #ifndef NO_DR_438_TEST std::deque > dq; dq.assign (1, 2); rw_assert (!DR_438::cast_used, 0, __LINE__, "deque::assign(InputIterator, InputIterator)" "with [ InputIterator = ] unexpectedly " "used explicit argument conversion"); dq.insert (dq.begin (), 1, 2); rw_assert (!DR_438::cast_used, 0, __LINE__, "deque::insert(iterator, InputIterator, InputIterator) " "with [ InputIterator = ] unexpectedly " "used explicit argument conversion"); #else // if defined (NO_DR_438_TEST) rw_warning (0, 0, __LINE__, "%s; skipping test", NO_DR_438_TEST); #endif // NO_DR_438_TEST } /**************************************************************************/ int run_test (int, char**) { test_dr_438 (); static const std::size_t caps[] = { 2, 3, 4, 5, 16, 32 }; for (std::size_t i = 0; i != sizeof caps / sizeof *caps; ++i) { new_capacity = caps [i]; rw_info (0, 0, 0, "__rw::__rw_new_capacity >(0) = %u", _RW::__rw_new_capacity (0, (Deque*)0)); test_assign (); test_erase (); test_insert (); } return 0; } /**************************************************************************/ int main (int argc, char** argv) { return rw_test (argc, argv, __FILE__, "lib.deque.modifiers", 0 /* no comment */, run_test, 0 /* co command line options */); } --------------060604020308020402090007--