blob: 5296ef5a24e8d4ec67bf2a6ce23152469d22bed7 [file] [log] [blame]
/************************************************************************
*
* 23.vector.allocator.cpp:
*
* Test exercising vector specialized on a user-defined allocator
* with a user-defined pointer type.
*
* $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 2007 Rogue Wave Software, Inc.
*
**************************************************************************/
// disable debug iterators to prevent compilation errors
#include <rw/_config.h>
#ifndef _RWSTD_NO_DEBUG_ITER
# define _RWSTD_NO_DEBUG_ITER
#endif // _RWSTD_NO_DEBUG_ITER
#include <memory>
#include <vector>
#include <cstddef> // for ptrdiff_t, size_t
#include <rw_driver.h>
/**************************************************************************/
// 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<T>::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 <class T>
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 T>
class Allocator
{
public:
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef Pointer<T> pointer;
typedef const Pointer<T> 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 <class U>
Allocator (const Allocator<U>&) 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 <class U>
struct rebind { typedef Allocator<U> 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<MyClass, Allocator<MyClass> >;
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
static int
run_test (int, char**)
{
rw_warn (0, 0, __LINE__, "debugging iterators disabled");
typedef std::vector<MyClass, Allocator<MyClass> > 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);
}