| /*************************************************************************** |
| * |
| * 23.deque.special.cpp - test exercising [lib.deque.special] |
| * |
| * $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 <deque> // for deque |
| |
| #include <cstddef> // for size_t |
| |
| #include <rw_value.h> // for UserClass |
| #include <driver.h> // for rw_test(), ... |
| |
| /**************************************************************************/ |
| |
| struct DequeValueType { }; |
| |
| typedef std::allocator<DequeValueType> DequeAllocator; |
| typedef std::deque<DequeValueType, DequeAllocator> DequeType; |
| |
| |
| int deque_swap_called; |
| |
| _RWSTD_NAMESPACE (std) { |
| |
| // define an explicit specialization of the deque::swap() member |
| // to verify tha the non-member swap function calls the member |
| |
| _RWSTD_SPECIALIZED_FUNCTION |
| void DequeType::swap (DequeType&) |
| { |
| ++deque_swap_called; |
| } |
| |
| } // namespace std |
| |
| /**************************************************************************/ |
| |
| void test_std_swap () |
| { |
| rw_info (0, 0, 0, |
| "Testing std::swap (std::deque&, std::deque&) " |
| "calls std::deque::swap"); |
| |
| // verify the signature of the function specialization |
| void (*pswap)(DequeType&, DequeType&) = |
| &std::swap<DequeValueType, DequeAllocator>; |
| |
| _RWSTD_UNUSED (pswap); |
| |
| // verify that std::swap() calls std::deque::swap() |
| DequeType d; |
| |
| std::swap (d, d); |
| |
| rw_assert (1 == deque_swap_called, 0, __LINE__, |
| "std::swap (std::deque<T, A>&, std::deque<T, A>&) called " |
| "std::deque<T, A>::swap (std::deque<T, A>&) exactly once; " |
| "got %d times", deque_swap_called); |
| } |
| |
| /**************************************************************************/ |
| |
| typedef std::deque<UserClass, std::allocator<UserClass> > Deque; |
| |
| Deque::size_type new_capacity; |
| |
| namespace __rw { |
| |
| _RWSTD_SPECIALIZED_FUNCTION |
| inline Deque::size_type |
| __rw_new_capacity<Deque>(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; |
| } |
| |
| } |
| |
| /**************************************************************************/ |
| |
| template <class T, class Allocator> |
| void test_swap (const T *lhs_seq, std::size_t lhs_seq_len, |
| const T *rhs_seq, std::size_t rhs_seq_len, |
| std::deque<T, Allocator>*, |
| const char *tname) |
| { |
| typedef std::deque<T, Allocator> Deque; |
| typedef typename Deque::iterator Iterator; |
| typedef typename Deque::size_type SizeType; |
| |
| // create two containers from the provided sequences |
| Deque lhs (lhs_seq, lhs_seq + lhs_seq_len); |
| Deque rhs (rhs_seq, rhs_seq + rhs_seq_len); |
| |
| // save the begin and and iterators and the size |
| // of each container before swapping the objects |
| const Iterator lhs_begin_0 = lhs.begin (); |
| const Iterator lhs_end_0 = lhs.end (); |
| const SizeType lhs_size_0 = lhs.size (); |
| |
| const Iterator rhs_begin_0 = rhs.begin (); |
| const Iterator rhs_end_0 = rhs.end (); |
| const SizeType rhs_size_0 = rhs.size (); |
| |
| // swap the two containers |
| lhs.swap (rhs); |
| |
| // compute the begin and and iterators and the size |
| // of each container after swapping the objects |
| const Iterator lhs_begin_1 = lhs.begin (); |
| const Iterator lhs_end_1 = lhs.end (); |
| const SizeType lhs_size_1 = lhs.size (); |
| |
| const Iterator rhs_begin_1 = rhs.begin (); |
| const Iterator rhs_end_1 = rhs.end (); |
| const SizeType rhs_size_1 = rhs.size (); |
| |
| // verify that the iterators and sizes |
| // of the two objects were swapped |
| rw_assert (lhs_begin_0 == rhs_begin_1 && lhs_begin_1 == rhs_begin_0, |
| 0, __LINE__, |
| "begin() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"", |
| int (lhs_seq_len), -1, lhs_seq, |
| int (rhs_seq_len), -1, rhs_seq); |
| |
| rw_assert (lhs_end_0 == rhs_end_1 && lhs_end_1 == rhs_end_0, |
| 0, __LINE__, |
| "end() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"", |
| int (lhs_seq_len), -1, lhs_seq, |
| int (rhs_seq_len), -1, rhs_seq); |
| |
| rw_assert (lhs_size_0 == rhs_size_1 && lhs_size_1 == rhs_size_0, |
| 0, __LINE__, |
| "size() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"", |
| int (lhs_seq_len), -1, lhs_seq, |
| int (rhs_seq_len), -1, rhs_seq); |
| |
| // swap one of the containers with an empty unnamed temporary |
| // container and verify that the object is empty |
| { Deque ().swap (lhs); } |
| |
| const Iterator lhs_begin_2 = lhs.begin (); |
| const Iterator lhs_end_2 = lhs.end (); |
| const SizeType lhs_size_2 = lhs.size (); |
| |
| rw_assert (lhs_begin_2 == lhs_end_2, 0, __LINE__, |
| "deque<%s>().begin() not swapped for \"%{X=*.*}\"", |
| tname, int (rhs_seq_len), -1, rhs_seq); |
| |
| rw_assert (0 == lhs_size_2, 0, __LINE__, |
| "deque<%s>().size() not swapped for \"%{X=*.*}\"", |
| tname, int (rhs_seq_len), -1, rhs_seq); |
| } |
| |
| |
| template <class T> |
| void test_swap (const T*, const char* tname) |
| { |
| rw_info (0, 0, 0, |
| "std::deque<%s>::swap(deque<%1$s>&)", tname); |
| |
| typedef std::deque<T, std::allocator<T> > MyDeque; |
| typedef typename MyDeque::iterator Iterator; |
| |
| // create two empty deque objects |
| MyDeque empty [2]; |
| |
| // save their begin and end iterators before calling swap |
| const Iterator before [2][2] = { |
| { empty [0].begin (), empty [0].end () }, |
| { empty [1].begin (), empty [1].end () } |
| }; |
| |
| // swap the two containers |
| empty [0].swap (empty [1]); |
| |
| // get the new begin and end iterators |
| const Iterator after [2][2] = { |
| { empty [0].begin (), empty [0].end () }, |
| { empty [1].begin (), empty [1].end () } |
| }; |
| |
| // verify that the iterators have not been invalidated |
| rw_assert ( before [0][0] == after [1][0] |
| && before [1][0] == after [0][0], 0, __LINE__, |
| "deque<%s>().begin() not swapped", tname); |
| |
| rw_assert ( before [0][1] == after [1][1] |
| && before [1][1] == after [0][1], 0, __LINE__, |
| "deque<%s>().end() not swapped", tname); |
| |
| // static to zero-initialize if T is a POD type |
| static T seq [32]; |
| |
| const std::size_t seq_len = sizeof seq / sizeof *seq; |
| |
| for (std::size_t i = 0; i != seq_len; ++i) { |
| for (std::size_t j = 0; j != seq_len; ++j) { |
| test_swap (seq, i, seq, j, (MyDeque*)0, tname); |
| } |
| } |
| } |
| |
| /**************************************************************************/ |
| |
| void test_swap () |
| { |
| test_swap ((int*)0, "int"); |
| test_swap ((UserClass*)0, "UserClass"); |
| } |
| |
| /**************************************************************************/ |
| |
| int run_test (int, char**) |
| { |
| // Test std::swap calling std::deque::swap |
| test_std_swap (); |
| |
| static const Deque::size_type 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<std::deque<UserClass> >(0) = %u", |
| _RW::__rw_new_capacity (0, (Deque*)0)); |
| |
| test_swap (); |
| } |
| |
| return 0; |
| } |
| |
| /**************************************************************************/ |
| |
| int main (int argc, char** argv) |
| { |
| return rw_test (argc, argv, __FILE__, |
| "lib.deque.special", |
| 0 /* no comment */, |
| run_test, |
| 0 /* co command line options */); |
| } |