/*************************************************************************** * * 25.swap.cpp - test exercising 25.2.2 [lib.alg.swap] * * $Id: 25.swap.cpp 510970 2007-02-23 14:57:45Z faridz $ * *************************************************************************** * * 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 1994-2006 Rogue Wave Software. * **************************************************************************/ #include // for swap, swap_ranges, iter_swap #include // for size_t, strlen() #include #include // for UserClass #include // for rw_test() _RWSTD_NAMESPACE (std) { // disable explicit instantiation for compilers (like MSVC) // that can't handle it #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION template void swap (assign >&, assign >&); template FwdIter > > swap_ranges (FwdIter > >, FwdIter > >, FwdIter > >); template void iter_swap (FwdIter > >, FwdIter > >); #endif // _RWSTD_NO_EXPLICIT_INSTANTIATION } // namespace std /**************************************************************************/ template void test_iter_swap (int line, const char* seq, ForwardIterator1 /* dummy */, ForwardIterator2 /* dummy */, const T* /* dummy */, bool it_swap, const char* it1name, const char* it2name, const char* fname) { // generate sequential values for each default constructed T const std::size_t nseq = std::strlen (seq); // construct a sequence of `nseq' elements to pass to swap T* const tseq = T::from_char (seq, nseq + 1); int a_val, b_val; bool success = true; std::size_t i = 1; for ( ; i < nseq; ++i) { const ForwardIterator1 it1 = make_iter (tseq, tseq, tseq + nseq, it1); const ForwardIterator2 it2 = make_iter (tseq + i, tseq, tseq + nseq, it2); a_val = (*it1).data_.val_; b_val = (*it2).data_.val_; it_swap ? std::iter_swap (it1, it2) : std::swap(*it1, *it2); // verify 25.2.2, p2, p7 success = a_val == (*it2).data_.val_ && b_val == (*it1).data_.val_; if (!success) break; } rw_assert (success, 0, line, "%s<%s%{?}, %s%{;}>(%#c, %#c): got: { %#c, %#c } " "expected: { %5$#c, %4$#c } at step %zu", fname, it1name, it_swap, it2name, a_val, b_val, tseq->data_.val_, (tseq + i)->data_.val_, i); delete[] tseq; } template void test_iter_swap (ForwardIterator1 it1, ForwardIterator2 it2, const T*, bool it_swap) { const char* const it1name = it_swap ? type_name (it1, (T*)0) : "UserClass"; const char* const it2name = it_swap ? type_name (it2, (T*)0) : "UserClass"; const char* const fname = it_swap ? "iter_swap" : "swap"; rw_info (0, 0, 0, "std::%s (%s, %s)", fname, it1name, it2name); #undef TEST #define TEST(seq) \ test_iter_swap (__LINE__, seq, it1, it2, (T*)0, it_swap, \ it1name, it2name, fname) TEST("ab"); TEST("abc"); TEST("abcd"); TEST("abcde"); TEST("abcdef"); TEST("abcdefg"); TEST("abcdefgh"); TEST("abcdefghi"); TEST("abcdefghij"); TEST("abcdefghijk"); } /**************************************************************************/ template void test_swap_ranges (int line, const char* seq1, const char* seq2, ForwardIterator1 it1, ForwardIterator2 it2, const T* /* dummy */, const char* it1name, const char* it2name) { const std::size_t nseq = std::strlen (seq1); // construct a sequence of `nseq' elements to pass to swap_ranges T* const tseq1 = T::from_char (seq1, nseq + 1); T* const tseq2 = T::from_char (seq2, nseq + 1); const ForwardIterator1 first1 = make_iter (tseq1, tseq1, tseq1 + nseq, it1); const ForwardIterator1 last1 = make_iter (tseq1 + nseq, tseq1, tseq1 + nseq, it1); const ForwardIterator2 first2 = make_iter (tseq2, tseq2, tseq2 + nseq, it2); const ForwardIterator2 last2 = make_iter (tseq2 + nseq, tseq2, tseq2 + nseq, it2); // silence bogus EDG eccp remark #550-D: variable was set // but never used _RWSTD_UNUSED (last2); T a, b; std::size_t last_n_op_assign = T::n_total_op_assign_; std::swap (a, b); std::size_t assigns_per_swap = T::n_total_op_assign_ - last_n_op_assign; last_n_op_assign = T::n_total_op_assign_; // exercise 25.2.3 - std::swap_ranges() const ForwardIterator2 res = std::swap_ranges(first1, last1, first2); // silence bogus EDG eccp remark #550-D: variable was set // but never used _RWSTD_UNUSED (res); // check the returned value, 25.2.2 p5 bool success = res.cur_ == last2.cur_; rw_assert (success, 0, line, "swap_ranges<%s, %s>(\"%s\", \"%s\") == first + %td, " "got first + %td", it1name, it2name, seq1, seq2, res.cur_ - tseq2, last2.cur_ - tseq2); // check that the sequences were swapped, 25.2.2 p4 std::size_t i = 0; for ( ; i < nseq; ++i) { success = (tseq1 + i)->data_.val_ == seq2[i] && (tseq2 + i)->data_.val_ == seq1[i]; if (!success) break; } rw_assert (success, 0, line, "swap_ranges<%s, %s>(\"%s\", \"%s\") mismatch at pos %zu " "got { %#c, %#c }, expected { %#c, %#c }", it1name, it2name, seq1, seq2, i, (tseq1 + i)->data_.val_, (tseq2 + i)->data_.val_, seq2[i], seq1[i]); // check the complexity, 25.2.2 p6 std::size_t swaps_per_swap_ranges = (T::n_total_op_assign_ - last_n_op_assign) / assigns_per_swap; rw_assert (swaps_per_swap_ranges == nseq, 0, line, "swap_ranges<%s, %s>(\"%s\", \"%s\") complexity: " "%zu, expected %zu swaps", it1name, it2name, seq1, seq2, swaps_per_swap_ranges, nseq); delete[] tseq1; delete[] tseq2; } /**************************************************************************/ template void test_swap_ranges (ForwardIterator1 it1, ForwardIterator2 it2, const T* /* dummy */) { static const char* const it1name = type_name (it1, (T*)0); static const char* const it2name = type_name (it2, (T*)0); rw_info (0, 0, 0, "std::swap_ranges (%s, %1$s, %s)", it1name, it2name); #undef TEST #define TEST(seq1, seq2) \ test_swap_ranges (__LINE__, seq1, seq2, it1, it2, (T*)0, \ it1name, it2name) TEST("", ""); TEST("a", "z"); TEST("ab", "zy"); TEST("abc", "zyx"); TEST("abcd", "zyxw"); TEST("abcde", "zyxwv"); TEST("abcdef", "zyxwvu"); TEST("abcdefg", "zyxwvut"); TEST("abcdefgh", "zyxwvuts"); TEST("abcdefghi", "zyxwvutsr"); TEST("abcdefghij", "zyxwvutsrq"); TEST("abcdefghijk", "zyxwvutsrqp"); TEST("abcdefghijkl", "zyxwvutsrqpo"); TEST("abcdefghijklm", "zyxwvutsrqpon"); } /**************************************************************************/ /* extern */ int rw_opt_no_swap; // --no-swap /* extern */ int rw_opt_no_swap_ranges; // --no-swap_ranges /* extern */ int rw_opt_no_iter_swap; // --no-iter_swap /* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator /* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator /* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator template void test_swap (ForwardIterator1 it1, const T*, bool test_ranges) { if (rw_opt_no_fwd_iter) { rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled"); } else { if (test_ranges) test_swap_ranges (it1, FwdIter(), (T*)0); else test_iter_swap (it1, FwdIter(), (T*)0, true); } if (rw_opt_no_bidir_iter) { rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled"); } else { if (test_ranges) test_swap_ranges (it1, BidirIter(), (T*)0); else test_iter_swap (it1, BidirIter(), (T*)0, true); } if (rw_opt_no_rnd_iter) { rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled"); } else { if (test_ranges) test_swap_ranges (it1, RandomAccessIter(), (T*)0); else test_iter_swap (it1, RandomAccessIter(), (T*)0, true); } } /**************************************************************************/ template void test_swap (const T*, bool test_ranges) { if (rw_opt_no_fwd_iter) { rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled"); } else { test_swap (FwdIter(), (T*)0, test_ranges); } if (rw_opt_no_bidir_iter) { rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled"); } else { test_swap (BidirIter(), (T*)0, test_ranges); } if (rw_opt_no_rnd_iter) { rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled"); } else { test_swap (RandomAccessIter(), (T*)0, test_ranges); } } /**************************************************************************/ static int run_test (int, char*[]) { if (rw_opt_no_swap) { rw_note (0, __FILE__, __LINE__, "std::swap test disabled"); } else { rw_info (0, 0, 0, "template void swap (T&, T&)"); test_iter_swap (FwdIter(), FwdIter(), (UserClass*)0, false); } if (rw_opt_no_swap_ranges) { rw_note (0, __FILE__, __LINE__, "std::swap_ranges test disabled"); } else { rw_info (0, 0, 0, "template %2$s " "swap_ranges (%1$s, %1$s, %2$s)", "ForwardIterator1", "ForwardIterator2"); test_swap ((UserClass*)0, true); } if (rw_opt_no_iter_swap) { rw_note (0, __FILE__, __LINE__, "std::iter_swap test disabled"); } else { rw_info (0, 0, 0, "template void iter_swap (%1$s, %2$s)", "ForwardIterator1", "ForwardIterator2"); test_swap ((UserClass*)0, false); } return 0; } /**************************************************************************/ int main (int argc, char *argv[]) { return rw_test (argc, argv, __FILE__, "lib.alg.swap", 0 /* no comment */, run_test, "|-no-swap# " "|-no-swap_ranges# " "|-no-iter_swap# " "|-no-ForwardIterator# " "|-no-BidirectionalIterator# " "|-no-RandomAccessIterator", &rw_opt_no_swap, &rw_opt_no_swap_ranges, &rw_opt_no_iter_swap, &rw_opt_no_fwd_iter, &rw_opt_no_bidir_iter, &rw_opt_no_rnd_iter); }