Author: sebor
Date: Thu Jul 17 14:58:05 2008
New Revision: 677756
URL: http://svn.apache.org/viewvc?rev=677756&view=rev
Log:
2008-07-17 Martin Sebor <[EMAIL PROTECTED]>
STDCXX-494
* include/vector (vector): Removed Allocator base class, replacing
it (in a binary compatible way) with a new member, _C_alloc, instead.
(_C_value_alloc_type): Removed member typedef.
(vector): Initialized the _C_alloc member instead of allocator_type
in all class ctors.
(~vector, begin, end, size, max_size, empty, swap): Referenced
_C_begin, _C_end, and _C_bufend indirectly, via the new _C_alloc
member.
(pop_back, push_back): Used the new _C_alloc member to destroy
and construct elements.
* include/vector.cc (_C_realloc, _C_destroy, _C_insert_1,
_C_insert_n, _C_insert_range): Same as above.
* tests/regress/23.vector.stdcxx-494: Added regression test for
the vector part of the issue.
Added:
stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp (with props)
Modified:
stdcxx/branches/4.2.x/include/vector
stdcxx/branches/4.2.x/include/vector.cc
Modified: stdcxx/branches/4.2.x/include/vector
URL:
http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/include/vector?rev=677756&r1=677755&r2=677756&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/include/vector (original)
+++ stdcxx/branches/4.2.x/include/vector Thu Jul 17 14:58:05 2008
@@ -88,7 +88,7 @@
_EXPORT
template <class _TypeT, class _Allocator>
-class vector: private _Allocator
+class vector
{
public:
@@ -100,7 +100,6 @@
typedef _TYPENAME allocator_type::const_reference const_reference;
typedef _TYPENAME allocator_type::pointer pointer;
typedef _TYPENAME allocator_type::const_pointer const_pointer;
- typedef _RWSTD_ALLOC_TYPE (allocator_type, value_type) _C_value_alloc_type;
public:
@@ -157,33 +156,32 @@
_EXPLICIT
vector (const allocator_type &__alloc = allocator_type ())
- : allocator_type (__alloc), _C_begin (), _C_end (), _C_bufend () { }
+ : _C_alloc (__alloc) { }
_EXPLICIT
vector (size_type __n, const_reference __x = value_type (),
const allocator_type &__alloc = allocator_type ())
- : allocator_type (__alloc), _C_begin (), _C_end (), _C_bufend () {
+ : _C_alloc (__alloc) {
assign (__n, __x);
}
template <class _InputIter>
vector (_InputIter __first, _InputIter __last,
const allocator_type &__alloc = allocator_type ())
- : allocator_type (__alloc), _C_begin (), _C_end (), _C_bufend () {
+ : _C_alloc (__alloc) {
assign (__first, __last);
}
vector (const vector &__rhs)
- : allocator_type (__rhs.get_allocator ()),
- _C_begin (), _C_end (), _C_bufend () {
+ : _C_alloc (__rhs.get_allocator ()) {
assign (__rhs.begin (), __rhs.end ());
}
~vector () {
- _C_destroy (begin ());
- _RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this,
- deallocate (_C_begin, _C_bufend - _C_begin));
+ _C_destroy (begin ());
+ _C_alloc.deallocate (_C_alloc._C_begin,
+ _C_alloc._C_bufend - _C_alloc._C_begin);
}
vector& operator= (const vector&);
@@ -199,23 +197,23 @@
}
allocator_type get_allocator () const {
- return *this;
+ return _C_alloc;
}
iterator begin () {
- return _C_make_iter (_C_begin);
+ return _C_make_iter (_C_alloc._C_begin);
}
const_iterator begin () const {
- return _C_make_iter (_C_begin);
+ return _C_make_iter (_C_alloc._C_begin);
}
iterator end () {
- return _C_make_iter (_C_end);
+ return _C_make_iter (_C_alloc._C_end);
}
const_iterator end () const {
- return _C_make_iter (_C_end);
+ return _C_make_iter (_C_alloc._C_end);
}
reverse_iterator rbegin () {
@@ -235,21 +233,21 @@
}
size_type size () const {
- return size_type (_C_end - _C_begin);
+ return size_type (_C_alloc._C_end - _C_alloc._C_begin);
}
size_type max_size () const {
- return _RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this, max_size ());
+ return _C_alloc.max_size ();
}
void resize (size_type, value_type = value_type ());
size_type capacity () const {
- return _C_bufend - _C_begin;
+ return _C_alloc._C_bufend - _C_alloc._C_begin;
}
bool empty () const {
- return _C_begin == _C_end;
+ return _C_alloc._C_begin == _C_alloc._C_end;
}
void reserve (size_type);
@@ -286,8 +284,8 @@
void pop_back () {
_RWSTD_ASSERT (!empty ());
- _RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this, destroy (_C_end - 1));
- --_C_end;
+ _C_alloc.destroy (_C_alloc._C_end - 1);
+ --_C_alloc._C_end;
}
iterator insert (iterator, const_reference);
@@ -393,11 +391,9 @@
// constructs a copy at the end and grows the size of container
void _C_push_back (const_reference __x) {
- _RWSTD_ASSERT (_C_end != _C_bufend);
-
- _RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this,
- construct (_C_end, __x));
- ++_C_end;
+ _RWSTD_ASSERT (_C_alloc._C_end != _C_alloc._C_bufend);
+ _C_alloc.construct (_C_alloc._C_end, __x);
+ ++_C_alloc._C_end;
}
// destroys elements from the iterator to the end of the vector
@@ -407,9 +403,16 @@
// implements swap for objects with unequal allocator
void _C_unsafe_swap (vector&);
- pointer _C_begin;
- pointer _C_end;
- pointer _C_bufend;
+ struct _C_VectorAlloc: allocator_type {
+
+ _C_VectorAlloc (const allocator_type &__alloc)
+ : allocator_type (__alloc), _C_begin (), _C_end (), _C_bufend ()
+ { /* empty */}
+
+ pointer _C_begin;
+ pointer _C_end;
+ pointer _C_bufend;
+ } _C_alloc;
};
@@ -507,12 +510,10 @@
vector<_TypeT, _Allocator>::
push_back (const_reference __x)
{
- if (_C_end == _C_bufend) {
+ if (_C_alloc._C_end == _C_alloc._C_bufend)
_C_insert_1 (end (), __x);
- }
- else {
+ else
_C_push_back (__x);
- }
}
@@ -547,8 +548,8 @@
if (__next != end ())
_STD::copy (__next, end (), __it);
- _RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this, destroy (_C_end - 1));
- --_C_end;
+ _C_alloc.destroy (_C_alloc._C_end - 1);
+ --_C_alloc._C_end;
return __it;
}
@@ -584,15 +585,15 @@
swap (vector &__other)
{
if (get_allocator () == __other.get_allocator ()) {
- pointer __tmp = _C_begin;
- _C_begin = __other._C_begin;
- __other._C_begin = __tmp;
- __tmp = _C_end;
- _C_end = __other._C_end;
- __other._C_end = __tmp;
- __tmp = _C_bufend;
- _C_bufend = __other._C_bufend;
- __other._C_bufend = __tmp;
+ pointer __tmp = _C_alloc._C_begin;
+ _C_alloc._C_begin = __other._C_alloc._C_begin;
+ __other._C_alloc._C_begin = __tmp;
+ __tmp = _C_alloc._C_end;
+ _C_alloc._C_end = __other._C_alloc._C_end;
+ __other._C_alloc._C_end = __tmp;
+ __tmp = _C_alloc._C_bufend;
+ _C_alloc._C_bufend = __other._C_alloc._C_bufend;
+ __other._C_alloc._C_bufend = __tmp;
}
else {
// not exception-safe
Modified: stdcxx/branches/4.2.x/include/vector.cc
URL:
http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/include/vector.cc?rev=677756&r1=677755&r2=677756&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/include/vector.cc (original)
+++ stdcxx/branches/4.2.x/include/vector.cc Thu Jul 17 14:58:05 2008
@@ -82,20 +82,19 @@
vector __tmp (get_allocator ());
// allocate storage of requested capacity
- __tmp._C_begin =
- _RWSTD_VALUE_ALLOC (_C_value_alloc_type, __tmp,
- allocate (__cap, this));
+ __tmp._C_alloc._C_begin = _C_alloc.allocate (__cap, this);
// initialize pointers
- __tmp._C_end = __tmp._C_begin;
- __tmp._C_bufend = __tmp._C_begin + __cap;
+ __tmp._C_alloc._C_end = __tmp._C_alloc._C_begin;
+ __tmp._C_alloc._C_bufend = __tmp._C_alloc._C_begin + __cap;
// copy *this into the temporary one element at a time, as if
// by calling std::unitialized_copy(), growing the temporary
// at each iteration so that an exception thrown by the copy
// ctor will cause the destruction of all already constructed
// elements (by invoking the temporary's dtor)
- for (pointer __ptr = _C_begin; !(__ptr == _C_end); ++__ptr) {
+ for (pointer __ptr = _C_alloc._C_begin; !(__ptr == _C_alloc._C_end);
+ ++__ptr) {
__tmp._C_push_back (*__ptr);
}
@@ -110,10 +109,8 @@
{
_RWSTD_ASSERT_RANGE (__first, end ());
- _C_value_alloc_type __alloc = _RWSTD_VALUE_ALLOC_CAST (*this);
-
for (size_type __n = end () - __first; !(0 == __n); --__n)
- __alloc.destroy (--_C_end);
+ _C_alloc.destroy (--_C_alloc._C_end);
}
@@ -170,12 +167,12 @@
if (__it < end ()) {
- const pointer __end = _C_end;
+ const pointer __end = _C_alloc._C_end;
// construct a copy of the last element in the range [it, end)
// in the uninitialized slot just past the end of the range
// and bump up end()
- _C_push_back (*(_C_end - difference_type (1)));
+ _C_push_back (*(_C_alloc._C_end - difference_type (1)));
// move the remaining elements from the range above one slot
// toward the end starting with the last element
@@ -218,36 +215,40 @@
vector __tmp (get_allocator ());
__tmp.reserve (__size2);
- _RWSTD_ASSERT (!(pointer () == __tmp._C_end));
+ _RWSTD_ASSERT (!(pointer () == __tmp._C_alloc._C_end));
iterator __i;
// copy the initial range prior to `it' as if by a call to
- // std::uninitialized_copy (begin (), __it, __tmp._C_begin);
+ // uninitialized_copy (begin (), __it, __tmp._C_alloc._C_begin);
for (__i = begin (); !(__i == __it); ++__i) {
- _RWSTD_ASSERT (!(__tmp._C_end == __tmp._C_bufend));
+ _RWSTD_ASSERT (!( __tmp._C_alloc._C_end
+ == __tmp._C_alloc._C_bufend));
__tmp._C_push_back (*__i);
}
// construct `n' copies of `x' just past the initial range,
// as if by a call to
- // std::uninitialized_fill_n (__tmp._C_begin + __size1, __n, __x);
+ // uninitialized_fill_n (__tmp._C_aloc._C_begin + __size1, __n, __x);
for ( ; __n; --__n) {
- _RWSTD_ASSERT (!(__tmp._C_end == __tmp._C_bufend));
+ _RWSTD_ASSERT (!( __tmp._C_alloc._C_end
+ == __tmp._C_alloc._C_bufend));
__tmp._C_push_back (__x);
}
// copy the final range of elements starting with `it'
// as if by a call to
- // uninitialized_copy (__it, end (), __tmp._C_begin + __size1 + __n);
+ // uninitialized_copy (__it, end (),
+ // __tmp._C_alloc._C_begin + __size1 + __n);
for (__i = __it; !(__i == end ()); ++__i) {
- _RWSTD_ASSERT (!(__tmp._C_end == __tmp._C_bufend));
+ _RWSTD_ASSERT (!( __tmp._C_alloc._C_end
+ == __tmp._C_alloc._C_bufend));
__tmp._C_push_back (*__i);
}
@@ -262,14 +263,12 @@
// controlled by *this that need to be moved (copy contructed past
// the end of the end of the sequence or assigned over existing
// elements)
- const pointer __movbeg = _C_begin + __size1;
+ const pointer __movbeg = _C_alloc._C_begin + __size1;
const pointer __movend = __movbeg + __n;
_RWSTD_ASSERT (_C_make_iter (__movbeg) == __it);
- _C_value_alloc_type __alloc = _RWSTD_VALUE_ALLOC_CAST (*this);
-
- if (__movend <= _C_end) {
+ if (__movend <= _C_alloc._C_end) {
// the end of the range of existing elements after being
// moved to make room for the elements to be inserted is
@@ -277,15 +276,16 @@
// compute the beginning of the range of elements whose copies
// will be constructed just past the current end of the sequence
- const pointer __ucpbeg = _C_end - __n;
- const pointer __ucpend = _C_end;
+ const pointer __ucpbeg = _C_alloc._C_end - __n;
+ const pointer __ucpend = _C_alloc._C_end;
// construct copies of elements that will be moved beyond
// the current end of the sequence controlled by *this
- _STD::uninitialized_copy (__ucpbeg, _C_end, _C_end, __alloc);
+ _STD::uninitialized_copy (__ucpbeg, _C_alloc._C_end,
+ _C_alloc._C_end, _C_alloc);
// advance end to maintain consistent state
- _C_end += __n;
+ _C_alloc._C_end += __n;
// copy elements the will be overwritten below
// over the range of elements moved above
@@ -299,17 +299,17 @@
const size_type __n1 = size () - __size1;
const size_type __n2 = __n - __n1;
- _STD::uninitialized_fill_n (_C_end, __n2, __x, __alloc);
+ _STD::uninitialized_fill_n (_C_alloc._C_end, __n2, __x, _C_alloc);
- const pointer __end = _C_end;
+ const pointer __end = _C_alloc._C_end;
- _C_end += __n2;
+ _C_alloc._C_end += __n2;
// construct copies of the range of elements [pos, end)
// past the end of the range of elements inserted above
- _STD::uninitialized_copy (__movbeg, __end, _C_end, __alloc);
+ _STD::uninitialized_copy (__movbeg, __end, _C_alloc._C_end, _C_alloc);
- _C_end += __end - __movbeg;
+ _C_alloc._C_end += __end - __movbeg;
__n = __n1;
}
@@ -527,23 +527,23 @@
if (__inx < __size) {
// swap the inserted elements with the elements before which
// they should be inserted, as if by calling
- // std::rotate (__beg, __mid, _C_end)
- const pointer __beg = __self->_C_begin + __inx;
- const pointer __mid = __self->_C_begin + __size;
+ // std::rotate (__beg, __mid, _C_alloc._C_end)
+ const pointer __beg = __self->_C_alloc._C_begin + __inx;
+ const pointer __mid = __self->_C_alloc._C_begin + __size;
if (__beg < __mid) {
for (pointer __p0 = __beg, __p1 = __mid; __p0 < --__p1; ++__p0)
_STD::iter_swap (__p0, __p1);
}
- if (__mid < __self->_C_end) {
- for (pointer __p0 = __mid, __p1 = __self->_C_end;
+ if (__mid < __self->_C_alloc._C_end) {
+ for (pointer __p0 = __mid, __p1 = __self->_C_alloc._C_end;
__p0 < --__p1; ++__p0)
_STD::iter_swap (__p0, __p1);
}
- if (__beg < __self->_C_end) {
- for (pointer __p0 = __beg, __p1 = __self->_C_end;
+ if (__beg < __self->_C_alloc._C_end) {
+ for (pointer __p0 = __beg, __p1 = __self->_C_alloc._C_end;
__p0 < --__p1; ++__p0)
_STD::iter_swap (__p0, __p1);
}
@@ -633,12 +633,12 @@
// in the sequence controlled by *this that need to be moved
// (copy contructed past the end of the end of the sequence
// or assigned over existing elements)
- const pointer __movbeg = __self->_C_begin + __size1;
+ const pointer __movbeg = __self->_C_alloc._C_begin + __size1;
const pointer __movend = __movbeg + __size2;
_RWSTD_ASSERT (__self->_C_make_iter (__movbeg) == __it);
- const pointer __end = __self->_C_end;
+ const pointer __end = __self->_C_alloc._C_end;
if (__movend <= __end) {
// compute the beginning of the range of elements whose copies
@@ -667,7 +667,7 @@
// construct copies of the trailing subsequence of the range
// of elements being inserted, as if by a call to
- // std::uninitialized_copy (__mid, __last, _C_end);
+ // std::uninitialized_copy (__mid, __last, _C_alloc._C_end);
for (_FwdIter __m = __mid ; !(__m == __last); ++__m)
__self->_C_push_back (*__m);
@@ -675,7 +675,7 @@
// construct copies of the range of elements [pos, end)
// past the end of the range of elements inserted above,
// as if by a call to
- // std::uninitialized_copy (__movbeg, __end, _C_end);
+ // std::uninitialized_copy (__movbeg, __end, _C_alloc._C_end);
for (pointer __p = __movbeg; !(__p == __end); ++__p)
__self->_C_push_back (*__p);
Added: stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp
URL:
http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp?rev=677756&view=auto
==============================================================================
--- stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp (added)
+++ stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp Thu Jul 17
14:58:05 2008
@@ -0,0 +1,71 @@
+/************************************************************************
+ *
+ * 23.vector.stdcxx-494.cpp - regression test for STDCXX-494
+ *
+ * https://issues.apache.org/jira/browse/STDCXX-611
+ *
+ * $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.
+ *
+ **************************************************************************/
+
+#include <cassert> // for assert()
+#include <cstddef> // for size_t
+#include <memory> // for allocator
+#include <vector> // for vector
+
+
+template <class T>
+struct EmptyAllocator: std::allocator<T>
+{
+ template <class U>
+ struct rebind { typedef EmptyAllocator<U> other; };
+
+ EmptyAllocator () { }
+ EmptyAllocator (const EmptyAllocator &rhs)
+ : std::allocator<T>(rhs) { }
+
+ template <class U>
+ EmptyAllocator (const EmptyAllocator<U> &rhs)
+ : std::allocator<T>(rhs) { }
+
+ void* operator new (std::size_t) { return 0; }
+ void operator delete (void*) { }
+};
+
+
+int main ()
+{
+ // verify that vector doesn't derive from allocator
+ // (otherwise the replacement operator new and delete
+ // are in conflict)
+
+ typedef std::vector<int, EmptyAllocator<int> > EmptyVector;
+
+ delete new EmptyVector;
+
+ // verifies empty base optimization
+ assert (sizeof (std::vector<int>) == sizeof (EmptyVector));
+
+ // assert that the size of vector is exactly 3 pointers
+ assert (sizeof (std::vector<int>) == 3 * sizeof (int*));
+
+ return 0;
+}
Propchange: stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: stdcxx/branches/4.2.x/tests/regress/23.vector.stdcxx-494.cpp
------------------------------------------------------------------------------
svn:keywords = Id