/************************************************************************ * * 23.vector.allocator.cpp: * * Test exercising vector specialized on a user-defined allocator * with a user-defined pointer type. * * $Id: 23.vector.allocator.cpp 588744 2007-10-26 18:51:03Z 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 2007 Rogue Wave Software, Inc. * **************************************************************************/ // disable debug iterators to prevent compilation errors #include #ifndef _RWSTD_NO_DEBUG_ITER # define _RWSTD_NO_DEBUG_ITER #endif // _RWSTD_NO_DEBUG_ITER #include #include #include // for ptrdiff_t, size_t #include /**************************************************************************/ // DESCRIPTION: // Test instantiates std::vector on a user-defined type, user-defined // allocator and a user-defined pointer type, making sure that everything // still compiles and runs with expected results // Note: 20.1.5, p2, Allocator requirements specifies that the type // std::allocator::pointer be a "pointer to T", which might // make this test case not well-defined; it is expected that // this will be changed in a future revision of the Standard // user-defined pointer type template struct Pointer { typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef std::random_access_iterator_tag iterator_category; Pointer (): offset_ (0) { } Pointer (const Pointer &rhs) : offset_ (rhs.offset_) { } Pointer (difference_type off, int) : offset_ (off) {} reference operator* () const { return *_RWSTD_REINTERPRET_CAST (pointer, offset_); } bool operator== (const Pointer &rhs) const { return offset_ == rhs.offset_; } bool operator!= (const Pointer &rhs) const { return !operator== (rhs); } bool operator< (const Pointer &rhs) const { return offset_ < rhs.offset_; } bool operator<= (const Pointer &rhs) const { return !(*this > rhs); } bool operator> (const Pointer &rhs) const { return rhs < *this; } bool operator>= (const Pointer &rhs) const { return !(*this < rhs); } Pointer& operator++ () { pointer ptr = _RWSTD_REINTERPRET_CAST (pointer, offset_); offset_ = _RWSTD_REINTERPRET_CAST (difference_type, ++ptr); return *this; } Pointer& operator-- () { pointer ptr = _RWSTD_REINTERPRET_CAST (pointer, offset_); offset_ = _RWSTD_REINTERPRET_CAST (difference_type, --ptr); return *this; } Pointer& operator+= (difference_type i) { pointer ptr = _RWSTD_REINTERPRET_CAST (pointer, offset_); offset_ = _RWSTD_REINTERPRET_CAST (difference_type, ptr += i); return *this; } Pointer& operator-= (difference_type i) { return *this += -i; } Pointer operator+ (difference_type i) const { return Pointer (*this) += i; } Pointer operator- (difference_type i) const { return Pointer (*this) -= i; } difference_type operator- (const Pointer &rhs) const { pointer p1 = _RWSTD_REINTERPRET_CAST (pointer, offset_); pointer p2 = _RWSTD_REINTERPRET_CAST (pointer, rhs.offset_); return p1 - p2; } difference_type offset_; private: // deliberately not defined to detect their use void operator++ (int); void operator-- (int); }; /**************************************************************************/ // user-defined allocator template class Allocator { public: typedef T value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef Pointer pointer; typedef const Pointer const_pointer; typedef T& reference; typedef const T& const_reference; typedef std::random_access_iterator_tag iterator_category; pointer address (reference r) const { return pointer (_RWSTD_REINTERPRET_CAST (difference_type, &r), 1); } const_pointer address (const_reference r) const { return const_pointer (_RWSTD_REINTERPRET_CAST (difference_type, &r), 1); } Allocator () throw () {} template Allocator (const Allocator&) throw () {} pointer allocate (size_type n, const void* = 0) { void* const ptr = operator new (n * sizeof (T)); return pointer (_RWSTD_REINTERPRET_CAST (difference_type, ptr), 1); } void deallocate (pointer ptr, size_type) { operator delete (_RWSTD_REINTERPRET_CAST (void*, ptr.offset_)); } void construct (pointer ptr, const_reference val) { new (_RWSTD_REINTERPRET_CAST (void*, ptr.offset_)) value_type (val); } void destroy (pointer ptr) { _RWSTD_REINTERPRET_CAST (T*, ptr.offset_)->~value_type (); } size_type max_size () const throw () { return size_type (-1) / sizeof (T); } template struct rebind { typedef Allocator other; }; bool operator== (const Allocator&) const { return 1; } bool operator!= (const Allocator &rhs) const { return !operator== (rhs); } }; /**************************************************************************/ // user-defined type struct MyClass { int i_; int j_; }; /**************************************************************************/ #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION // explicitly instantiate to better exercise the template template class std::vector >; #endif // _RWSTD_NO_EXPLICIT_INSTANTIATION static int run_test (int, char**) { rw_warn (0, 0, __LINE__, "debugging iterators disabled"); typedef std::vector > Vector; const Vector::size_type nelems = 256; const MyClass value = { 0, 0 }; Vector v (nelems, value); rw_assert (nelems == v.size (), 0, __LINE__, "vector(%zu, value_type).size() == %1$zu, got %zu", nelems, v.size ()); Vector ().swap (v); rw_assert (0 == v.size (), 0, __LINE__, "vector().swap(vector&).size() == 0, got %zu", v.size ()); Vector::size_type i; for (i = 0; i != nelems; ++i) v.push_back (value); rw_assert (nelems == v.size (), 0, __LINE__, "vector::size() == %1$zu, got %zu", nelems, v.size ()); return 0; } /**************************************************************************/ int main (int argc, char** argv) { return rw_test (argc, argv, __FILE__, "lib.vector", "with a user-defined allocator and pointer types", run_test, "", (void*)0); }