| /*************************************************************************** |
| * |
| * 25.swap.cpp - test exercising 25.2.2 [lib.alg.swap] |
| * |
| * $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 1994-2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| #include <algorithm> // for swap, swap_ranges, iter_swap |
| #include <cstring> // for size_t, strlen() |
| |
| #include <alg_test.h> |
| #include <rw_value.h> // for UserClass |
| #include <driver.h> // 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<base<cpy_ctor> >&, assign<base<cpy_ctor> >&); |
| |
| template |
| FwdIter<assign<base<cpy_ctor> > > |
| swap_ranges (FwdIter<assign<base<cpy_ctor> > >, |
| FwdIter<assign<base<cpy_ctor> > >, |
| FwdIter<assign<base<cpy_ctor> > >); |
| |
| template |
| void |
| iter_swap (FwdIter<assign<base<cpy_ctor> > >, |
| FwdIter<assign<base<cpy_ctor> > >); |
| |
| #endif // _RWSTD_NO_EXPLICIT_INSTANTIATION |
| |
| } // namespace std |
| |
| /**************************************************************************/ |
| |
| template <class T, class ForwardIterator1, class ForwardIterator2> |
| 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 <class T, class ForwardIterator1, class ForwardIterator2> |
| 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 <class T, class ForwardIterator1, class ForwardIterator2> |
| 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 <class T, class ForwardIterator1, class ForwardIterator2> |
| 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 <class T, class ForwardIterator1> |
| 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>(), (T*)0); |
| else |
| test_iter_swap (it1, FwdIter<T>(), (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>(), (T*)0); |
| else |
| test_iter_swap (it1, BidirIter<T>(), (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>(), (T*)0); |
| else |
| test_iter_swap (it1, RandomAccessIter<T>(), (T*)0, true); |
| } |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T> |
| 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>(), (T*)0, test_ranges); |
| } |
| |
| if (rw_opt_no_bidir_iter) { |
| rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled"); |
| } |
| else { |
| test_swap (BidirIter<T>(), (T*)0, test_ranges); |
| } |
| |
| if (rw_opt_no_rnd_iter) { |
| rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled"); |
| } |
| else { |
| test_swap (RandomAccessIter<T>(), (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 <class T> void swap (T&, T&)"); |
| |
| test_iter_swap (FwdIter<UserClass>(), FwdIter<UserClass>(), |
| (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 <class %s, class %s> %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 <class %s, class %s> 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); |
| } |