* [v3] add <scoped_allocator>
@ 2011-07-09 14:44 Jonathan Wakely
2011-07-18 17:08 ` Jonathan Wakely
0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2011-07-09 14:44 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 838 bytes --]
This adds the new <scoped_allocator> header. Currently only
std::vector has the necessary support for C++0x allocators to be
usable with std::scoped_allocator_adaptor.
* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/std/scoped_allocator: New.
* doc/xml/manual/status_cxx200x.xml: Update.
* testsuite/20_util/scoped_allocator/1.cc: New.
* testsuite/20_util/scoped_allocator/propagation.cc: New.
* testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
* testsuite/20_util/scoped_allocator/requirements/
explicit_instantiation.cc: New.
Tested x86_64-linux, commited to trunk
Remaining allocator work is to make the other containers and
std::shared_ptr use the new C++0x model, and make std::function use an
allocator.
[-- Attachment #2: allocs.txt --]
[-- Type: text/plain, Size: 28529 bytes --]
Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h (revision 176072)
+++ include/bits/stl_vector.h (working copy)
@@ -71,13 +71,15 @@
struct _Vector_base
{
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
+ pointer;
struct _Vector_impl
: public _Tp_alloc_type
{
- typename _Tp_alloc_type::pointer _M_start;
- typename _Tp_alloc_type::pointer _M_finish;
- typename _Tp_alloc_type::pointer _M_end_of_storage;
+ pointer _M_start;
+ pointer _M_finish;
+ pointer _M_end_of_storage;
_Vector_impl()
: _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
@@ -93,6 +95,13 @@
_M_start(0), _M_finish(0), _M_end_of_storage(0)
{ }
#endif
+
+ void _M_swap_data(_Vector_impl& __x)
+ {
+ std::swap(_M_start, __x._M_start);
+ std::swap(_M_finish, __x._M_finish);
+ std::swap(_M_end_of_storage, __x._M_end_of_storage);
+ }
};
public:
@@ -118,30 +127,30 @@
_Vector_base(size_t __n)
: _M_impl()
- {
- this->_M_impl._M_start = this->_M_allocate(__n);
- this->_M_impl._M_finish = this->_M_impl._M_start;
- this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
- }
+ { _M_create_storage(__n); }
_Vector_base(size_t __n, const allocator_type& __a)
: _M_impl(__a)
- {
- this->_M_impl._M_start = this->_M_allocate(__n);
- this->_M_impl._M_finish = this->_M_impl._M_start;
- this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
- }
+ { _M_create_storage(__n); }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ _Vector_base(_Tp_alloc_type&& __a)
+ : _M_impl(std::move(__a)) { }
+
_Vector_base(_Vector_base&& __x)
: _M_impl(std::move(__x._M_get_Tp_allocator()))
+ { this->_M_impl._M_swap_data(__x._M_impl); }
+
+ _Vector_base(_Vector_base&& __x, const allocator_type& __a)
+ : _M_impl(__a)
{
- this->_M_impl._M_start = __x._M_impl._M_start;
- this->_M_impl._M_finish = __x._M_impl._M_finish;
- this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage;
- __x._M_impl._M_start = 0;
- __x._M_impl._M_finish = 0;
- __x._M_impl._M_end_of_storage = 0;
+ if (__x.get_allocator() == __a)
+ this->_M_impl._M_swap_data(__x._M_impl);
+ else
+ {
+ size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start;
+ _M_create_storage(__n);
+ }
}
#endif
@@ -152,16 +161,25 @@
public:
_Vector_impl _M_impl;
- typename _Tp_alloc_type::pointer
+ pointer
_M_allocate(size_t __n)
{ return __n != 0 ? _M_impl.allocate(__n) : 0; }
void
- _M_deallocate(typename _Tp_alloc_type::pointer __p, size_t __n)
+ _M_deallocate(pointer __p, size_t __n)
{
if (__p)
_M_impl.deallocate(__p, __n);
}
+
+ private:
+ void
+ _M_create_storage(size_t __n)
+ {
+ this->_M_impl._M_start = this->_M_allocate(__n);
+ this->_M_impl._M_finish = this->_M_impl._M_start;
+ this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
+ }
};
@@ -196,10 +214,11 @@
public:
typedef _Tp value_type;
- typedef typename _Tp_alloc_type::pointer pointer;
- typedef typename _Tp_alloc_type::const_pointer const_pointer;
- typedef typename _Tp_alloc_type::reference reference;
- typedef typename _Tp_alloc_type::const_reference const_reference;
+ typedef typename _Base::pointer pointer;
+ typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits;
+ typedef typename _Alloc_traits::const_pointer const_pointer;
+ typedef typename _Alloc_traits::reference reference;
+ typedef typename _Alloc_traits::const_reference const_reference;
typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
typedef __gnu_cxx::__normal_iterator<const_pointer, vector>
const_iterator;
@@ -283,7 +302,8 @@
* @a x (for fast expansion) will not be copied.
*/
vector(const vector& __x)
- : _Base(__x.size(), __x._M_get_Tp_allocator())
+ : _Base(__x.size(),
+ _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
{ this->_M_impl._M_finish =
std::__uninitialized_copy_a(__x.begin(), __x.end(),
this->_M_impl._M_start,
@@ -301,6 +321,29 @@
vector(vector&& __x) noexcept
: _Base(std::move(__x)) { }
+ /// Copy constructor with alternative allocator
+ vector(const vector& __x, const allocator_type& __a)
+ : _Base(__x.size(), __a)
+ { this->_M_impl._M_finish =
+ std::__uninitialized_copy_a(__x.begin(), __x.end(),
+ this->_M_impl._M_start,
+ _M_get_Tp_allocator());
+ }
+
+ /// Move constructor with alternative allocator
+ vector(vector&& __rv, const allocator_type& __m)
+ : _Base(std::move(__rv), __m)
+ {
+ if (__rv.get_allocator() != __m)
+ {
+ this->_M_impl._M_finish =
+ std::__uninitialized_move_a(__rv.begin(), __rv.end(),
+ this->_M_impl._M_start,
+ _M_get_Tp_allocator());
+ __rv.clear();
+ }
+ }
+
/**
* @brief Builds a %vector from an initializer list.
* @param l An initializer_list.
@@ -377,12 +420,32 @@
* @a x is a valid, but unspecified %vector.
*/
vector&
- operator=(vector&& __x)
+ operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
{
- // NB: DR 1204.
- // NB: DR 675.
- this->clear();
- this->swap(__x);
+ if (_Alloc_traits::_S_propagate_on_move_assign())
+ {
+ // We're moving the rvalue's allocator so can move the data too.
+ const vector __tmp(std::move(*this)); // discard existing data
+ this->_M_impl._M_swap_data(__x._M_impl);
+ std::__alloc_on_move(_M_get_Tp_allocator(),
+ __x._M_get_Tp_allocator());
+ }
+ else if (_Alloc_traits::_S_always_equal()
+ || __x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
+ {
+ // The rvalue's allocator can free our storage and vice versa,
+ // so can swap the data storage after destroying our contents.
+ this->clear();
+ this->_M_impl._M_swap_data(__x._M_impl);
+ }
+ else
+ {
+ // The rvalue's allocator cannot be moved, or is not equal,
+ // so we need to individually move each element.
+ this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
+ std::__make_move_if_noexcept_iterator(__x.end()));
+ __x.clear();
+ }
return *this;
}
@@ -834,7 +897,8 @@
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
- this->_M_impl.construct(this->_M_impl._M_finish, __x);
+ _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
+ __x);
++this->_M_impl._M_finish;
}
else
@@ -864,7 +928,7 @@
pop_back()
{
--this->_M_impl._M_finish;
- this->_M_impl.destroy(this->_M_impl._M_finish);
+ _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -1024,16 +1088,13 @@
*/
void
swap(vector& __x)
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ noexcept(_Alloc_traits::_S_nothrow_swap())
+#endif
{
- std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
- std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
- std::swap(this->_M_impl._M_end_of_storage,
- __x._M_impl._M_end_of_storage);
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 431. Swapping containers with unequal allocators.
- std::__alloc_swap<_Tp_alloc_type>::_S_do_it(_M_get_Tp_allocator(),
- __x._M_get_Tp_allocator());
+ this->_M_impl._M_swap_data(__x._M_impl);
+ _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),
+ __x._M_get_Tp_allocator());
}
/**
Index: include/bits/vector.tcc
===================================================================
--- include/bits/vector.tcc (revision 176072)
+++ include/bits/vector.tcc (working copy)
@@ -94,8 +94,8 @@
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
- this->_M_impl.construct(this->_M_impl._M_finish,
- std::forward<_Args>(__args)...);
+ _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
+ std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
}
else
@@ -112,7 +112,7 @@
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
&& __position == end())
{
- this->_M_impl.construct(this->_M_impl._M_finish, __x);
+ _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);
++this->_M_impl._M_finish;
}
else
@@ -138,7 +138,7 @@
if (__position + 1 != end())
_GLIBCXX_MOVE3(__position + 1, end(), __position);
--this->_M_impl._M_finish;
- this->_M_impl.destroy(this->_M_impl._M_finish);
+ _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
return __position;
}
@@ -160,6 +160,22 @@
{
if (&__x != this)
{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ if (_Alloc_traits::_S_propagate_on_copy_assign())
+ {
+ if (!_Alloc_traits::_S_always_equal()
+ && _M_get_Tp_allocator() != __x._M_get_Tp_allocator())
+ {
+ // replacement allocator cannot free existing storage
+ this->clear();
+ _M_deallocate(this->_M_impl._M_start,
+ this->_M_impl._M_end_of_storage
+ - this->_M_impl._M_start);
+ }
+ std::__alloc_on_copy(_M_get_Tp_allocator(),
+ __x._M_get_Tp_allocator());
+ }
+#endif
const size_type __xlen = __x.size();
if (__xlen > capacity())
{
@@ -277,8 +293,8 @@
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
&& __position == end())
{
- this->_M_impl.construct(this->_M_impl._M_finish,
- std::forward<_Args>(__args)...);
+ _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
+ std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
}
else
@@ -300,9 +316,9 @@
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
- this->_M_impl.construct(this->_M_impl._M_finish,
- _GLIBCXX_MOVE(*(this->_M_impl._M_finish
- - 1)));
+ _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
+ _GLIBCXX_MOVE(*(this->_M_impl._M_finish
+ - 1)));
++this->_M_impl._M_finish;
#ifndef __GXX_EXPERIMENTAL_CXX0X__
_Tp __x_copy = __x;
@@ -329,11 +345,12 @@
// case, where the moves could alter a new element belonging
// to the existing vector. This is an issue only for callers
// taking the element by const lvalue ref (see 23.1/13).
- this->_M_impl.construct(__new_start + __elems_before,
+ _Alloc_traits::construct(this->_M_impl,
+ __new_start + __elems_before,
#ifdef __GXX_EXPERIMENTAL_CXX0X__
- std::forward<_Args>(__args)...);
+ std::forward<_Args>(__args)...);
#else
- __x);
+ __x);
#endif
__new_finish = 0;
@@ -352,7 +369,8 @@
__catch(...)
{
if (!__new_finish)
- this->_M_impl.destroy(__new_start + __elems_before);
+ _Alloc_traits::destroy(this->_M_impl,
+ __new_start + __elems_before);
else
std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
_M_deallocate(__new_start, __len);
Index: testsuite/util/testsuite_allocator.h
===================================================================
--- testsuite/util/testsuite_allocator.h (revision 176072)
+++ testsuite/util/testsuite_allocator.h (working copy)
@@ -371,6 +371,68 @@
int personality;
};
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ // An uneq_allocator which can be used to test allocator propagation.
+ template<typename Tp, bool Propagate>
+ class propagating_allocator : public uneq_allocator<Tp>
+ {
+ typedef uneq_allocator<Tp> base_alloc;
+ base_alloc& base() { return *this; }
+ const base_alloc& base() const { return *this; }
+ void swap_base(base_alloc& b) { swap(b, this->base()); }
+
+ typedef std::integral_constant<bool, Propagate> trait_type;
+
+ public:
+ template<typename Up>
+ struct rebind { typedef propagating_allocator<Up, Propagate> other; };
+
+ propagating_allocator(int i) noexcept
+ : base_alloc(i)
+ { }
+
+ template<typename Up>
+ propagating_allocator(const propagating_allocator<Up, Propagate>& a)
+ noexcept
+ : base_alloc(a)
+ { }
+
+ propagating_allocator() noexcept = default;
+
+ propagating_allocator(const propagating_allocator&) noexcept = default;
+
+ template<bool P2>
+ propagating_allocator&
+ operator=(const propagating_allocator<Tp, P2>& a) noexcept
+ {
+ static_assert(P2, "assigning propagating_allocator<T, true>");
+ propagating_allocator(a).swap_base(*this);
+ }
+
+ // postcondition: a.get_personality() == 0
+ propagating_allocator(propagating_allocator&& a) noexcept
+ : base_alloc()
+ { swap_base(a); }
+
+ // postcondition: a.get_personality() == 0
+ propagating_allocator&
+ operator=(propagating_allocator&& a) noexcept
+ {
+ propagating_allocator(std::move(a)).swap_base(*this);
+ return *this;
+ }
+
+ typedef trait_type propagate_on_container_copy_assignment;
+ typedef trait_type propagate_on_container_move_assignment;
+ typedef trait_type propagate_on_container_swap;
+
+ propagating_allocator select_on_container_copy_construction() const
+ { return Propagate ? *this : propagating_allocator(); }
+ };
+
+#endif
+
} // namespace __gnu_test
#endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H
Index: testsuite/23_containers/vector/allocator/copy_assign.cc
===================================================================
--- testsuite/23_containers/vector/allocator/copy_assign.cc (revision 0)
+++ testsuite/23_containers/vector/allocator/copy_assign.cc (revision 0)
@@ -0,0 +1,57 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, false> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ v2 = v1;
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, true> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ v2 = v1;
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/23_containers/vector/allocator/noexcept.cc
===================================================================
--- testsuite/23_containers/vector/allocator/noexcept.cc (revision 0)
+++ testsuite/23_containers/vector/allocator/noexcept.cc (revision 0)
@@ -0,0 +1,76 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+namespace __gnu_test
+{
+ inline void
+ swap(propagating_allocator<T, true>& l, propagating_allocator<T, true>& r)
+ noexcept(false)
+ {
+ typedef uneq_allocator<T> base_alloc;
+ swap(static_cast<base_alloc&>(l), static_cast<base_alloc&>(r));
+ }
+}
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ typedef std::allocator<T> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1;
+ test_type v2;
+ // this is a GNU extension for std::allocator
+ static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" );
+ static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
+}
+
+void test02()
+{
+ typedef propagating_allocator<T, false> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ static_assert( !noexcept( v1 = std::move(v2) ), "Move assign can throw" );
+ static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
+}
+
+void test03()
+{
+ typedef propagating_allocator<T, true> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" );
+ static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" );
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
Index: testsuite/23_containers/vector/allocator/copy.cc
===================================================================
--- testsuite/23_containers/vector/allocator/copy.cc (revision 0)
+++ testsuite/23_containers/vector/allocator/copy.cc (revision 0)
@@ -0,0 +1,55 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, false> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(v1);
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(0 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, true> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(v1);
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/23_containers/vector/allocator/swap.cc
===================================================================
--- testsuite/23_containers/vector/allocator/swap.cc (revision 0)
+++ testsuite/23_containers/vector/allocator/swap.cc (revision 0)
@@ -0,0 +1,57 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, false> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ std::swap(v1, v2);
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, true> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ std::swap(v1, v2);
+ VERIFY(2 == v1.get_allocator().get_personality());
+ VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/23_containers/vector/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/vector/allocator/move_assign.cc (revision 0)
+++ testsuite/23_containers/vector/allocator/move_assign.cc (revision 0)
@@ -0,0 +1,57 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, false> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ v2 = std::move(v1);
+ VERIFY(1 == v1.get_allocator().get_personality());
+ VERIFY(2 == v2.get_allocator().get_personality());
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ typedef propagating_allocator<T, true> alloc_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ test_type v2(alloc_type(2));
+ v2 = std::move(v1);
+ VERIFY(0 == v1.get_allocator().get_personality());
+ VERIFY(1 == v2.get_allocator().get_personality());
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
Index: testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (revision 176072)
+++ testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1157 }
+// { dg-error "no matching" "" { target *-*-* } 1218 }
#include <vector>
Index: testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (revision 176072)
+++ testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1198 }
+// { dg-error "no matching" "" { target *-*-* } 1259 }
#include <vector>
Index: testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (revision 176072)
+++ testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1087 }
+// { dg-error "no matching" "" { target *-*-* } 1148 }
#include <vector>
Index: testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (revision 176072)
+++ testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (working copy)
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1087 }
+// { dg-error "no matching" "" { target *-*-* } 1148 }
#include <vector>
#include <utility>
Index: doc/xml/manual/status_cxx200x.xml
===================================================================
--- doc/xml/manual/status_cxx200x.xml (revision 176078)
+++ doc/xml/manual/status_cxx200x.xml (working copy)
@@ -1009,52 +1009,47 @@ particular release.
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.12</entry>
<entry>Scoped allocator adaptor</entry>
- <entry/>
+ <entry>Partial</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.1</entry>
<entry>Header <code><scoped_allocator></code> synopsis</entry>
<entry/>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.2</entry>
<entry>Scoped allocator adaptor member types</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.3</entry>
<entry>Scoped allocator adaptor constructors</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.12.4</entry>
<entry>Scoped allocator adaptor members</entry>
- <entry>N</entry>
+ <entry>Partial</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.5</entry>
<entry>Scoped allocator operators</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.13</entry>
<entry>Class <code>type_index</code></entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [v3] add <scoped_allocator>
2011-07-09 14:44 [v3] add <scoped_allocator> Jonathan Wakely
@ 2011-07-18 17:08 ` Jonathan Wakely
2011-07-20 15:55 ` Ed Smith-Rowland
0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2011-07-18 17:08 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 901 bytes --]
On 9 July 2011 14:46, Jonathan Wakely wrote:
> This adds the new <scoped_allocator> header. Currently only
> std::vector has the necessary support for C++0x allocators to be
> usable with std::scoped_allocator_adaptor.
>
> * include/Makefile.am: Add new header.
> * include/Makefile.in: Regenerate.
> * include/std/scoped_allocator: New.
> * doc/xml/manual/status_cxx200x.xml: Update.
> * testsuite/20_util/scoped_allocator/1.cc: New.
> * testsuite/20_util/scoped_allocator/propagation.cc: New.
> * testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
> * testsuite/20_util/scoped_allocator/requirements/
> explicit_instantiation.cc: New.
>
> Tested x86_64-linux, commited to trunk
Thanks to Francois for pointing out I attached the wrong patch, this
is the patch matching the changelog above, in r176079
[-- Attachment #2: sa.txt --]
[-- Type: text/plain, Size: 28793 bytes --]
Index: doc/xml/manual/status_cxx200x.xml
===================================================================
--- doc/xml/manual/status_cxx200x.xml (revision 176078)
+++ doc/xml/manual/status_cxx200x.xml (revision 176079)
@@ -1009,52 +1009,47 @@
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.12</entry>
<entry>Scoped allocator adaptor</entry>
+ <entry>Partial</entry>
<entry/>
- <entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.1</entry>
<entry>Header <code><scoped_allocator></code> synopsis</entry>
<entry/>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.2</entry>
<entry>Scoped allocator adaptor member types</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.3</entry>
<entry>Scoped allocator adaptor constructors</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.12.4</entry>
<entry>Scoped allocator adaptor members</entry>
- <entry>N</entry>
+ <entry>Partial</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.12.5</entry>
<entry>Scoped allocator operators</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>20.13</entry>
<entry>Class <code>type_index</code></entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
Index: include/Makefile.in
===================================================================
--- include/Makefile.in (revision 176078)
+++ include/Makefile.in (revision 176079)
@@ -310,6 +310,7 @@
${std_srcdir}/random \
${std_srcdir}/ratio \
${std_srcdir}/regex \
+ ${std_srcdir}/scoped_allocator \
${std_srcdir}/set \
${std_srcdir}/sstream \
${std_srcdir}/stack \
Index: include/std/scoped_allocator
===================================================================
--- include/std/scoped_allocator (revision 0)
+++ include/std/scoped_allocator (revision 176079)
@@ -0,0 +1,373 @@
+// <scoped_allocator> -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/scoped_allocator
+ * This is a Standard C++ Library header.
+ */
+
+#ifndef _SCOPED_ALLOCATOR
+#define _SCOPED_ALLOCATOR 1
+
+#pragma GCC system_header
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <bits/c++0x_warning.h>
+#else
+
+#include <utility>
+#include <tuple>
+#include <bits/alloc_traits.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<template<typename> class _Pred, typename... _Allocs>
+ struct __any_of;
+
+ template<template<typename> class _Pred, typename _Alloc, typename... _Allocs>
+ struct __any_of<_Pred, _Alloc, _Allocs...>
+ : __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>>
+ { };
+
+ template<template<typename> class _Pred, typename _Alloc>
+ struct __any_of<_Pred, _Alloc>
+ : _Pred<_Alloc>
+ { };
+
+ /**
+ * @addtogroup allocators
+ * @{
+ */
+
+ template<typename _Alloc>
+ struct __propagate_on_copy
+ : allocator_traits<_Alloc>::propagate_on_container_copy_assignment
+ { };
+ template<typename _Alloc>
+ struct __propagate_on_move
+ : allocator_traits<_Alloc>::propagate_on_container_move_assignment
+ { };
+ template<typename _Alloc>
+ struct __propagate_on_swap
+ : allocator_traits<_Alloc>::propagate_on_container_swap
+ { };
+
+
+ template<typename _Alloc>
+ inline auto
+ __do_outermost(_Alloc& __a, _Alloc&) -> decltype(__a.outer_allocator())
+ { return __a.outer_allocator(); }
+
+ template<typename _Alloc>
+ inline _Alloc&
+ __do_outermost(_Alloc& __a, ...)
+ { return __a; }
+
+ template<typename _Alloc>
+ inline auto
+ __outermost(_Alloc& __a) -> decltype(__do_outermost(__a, __a))
+ { return __do_outermost(__a, __a); }
+
+ template<typename _OuterAlloc, typename... _InnerAllocs>
+ class scoped_allocator_adaptor;
+
+ template<typename...> struct __inner_type_impl;
+
+ template<typename _Outer>
+ struct __inner_type_impl<_Outer>
+ {
+ typedef scoped_allocator_adaptor<_Outer> __type;
+
+ __inner_type_impl() = default;
+ __inner_type_impl(const __inner_type_impl&) = default;
+ __inner_type_impl(__inner_type_impl&&) = default;
+
+ template<typename _Alloc>
+ __inner_type_impl(const __inner_type_impl<_Alloc>& __other)
+ { }
+
+ template<typename _Alloc>
+ __inner_type_impl(__inner_type_impl<_Alloc>&& __other)
+ { }
+
+ __type& _M_get(__type* __p) noexcept { return *__p; }
+ const __type& _M_get(const __type* __p) const noexcept { return *__p; }
+
+ tuple<> _M_tie() const noexcept { return tuple<>(); }
+
+ bool operator==(const __inner_type_impl&) const noexcept
+ { return true; }
+ };
+
+ template<typename _Outer, typename _InnerHead, typename... _InnerTail>
+ struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...>
+ {
+ typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type;
+
+ __inner_type_impl() = default;
+ __inner_type_impl(const __inner_type_impl&) = default;
+ __inner_type_impl(__inner_type_impl&&) = default;
+
+ template<typename... _Allocs>
+ __inner_type_impl(const __inner_type_impl<_Allocs...>& __other)
+ : _M_inner(__other._M_inner) { }
+
+ template<typename... _Allocs>
+ __inner_type_impl(__inner_type_impl<_Allocs...>&& __other)
+ : _M_inner(std::move(__other._M_inner)) { }
+
+ template<typename... _Args>
+ explicit
+ __inner_type_impl(_Args&&... __args)
+ : _M_inner(std::forward<_Args>(__args)...) { }
+
+ __type& _M_get(void*) noexcept { return _M_inner; }
+ const __type& _M_get(const void*) const noexcept { return _M_inner; }
+
+ tuple<const _InnerHead&, const _InnerTail&...> _M_tie() const noexcept
+ { return _M_inner._M_tie(); }
+
+ bool operator==(const __inner_type_impl& __other) const noexcept
+ { return _M_inner == __other._M_inner; }
+
+ private:
+ template<typename...> friend class __inner_type_impl;
+ template<typename, typename...> friend class scoped_allocator_adaptor;
+
+ __type _M_inner;
+ };
+
+ template<typename _OuterAlloc, typename... _InnerAllocs>
+ class scoped_allocator_adaptor
+ : public _OuterAlloc
+ {
+ typedef allocator_traits<_OuterAlloc> __traits;
+
+ typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type;
+ __inner_type _M_inner;
+
+ template<typename _Outer, typename... _Inner>
+ friend class scoped_allocator_adaptor;
+
+ template<typename...>
+ friend class __inner_type_impl;
+
+ tuple<const _OuterAlloc&, const _InnerAllocs&...>
+ _M_tie() const noexcept
+ { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); }
+
+
+ template<typename _Tp, typename... _Args>
+ void _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args)
+ {
+ auto& __outer = __outermost(*this);
+ typedef typename std::decay<decltype(__outer)>::type __outer_type;
+ typedef allocator_traits<__outer_type> __o_traits;
+ __o_traits::construct(__outer, __p, std::forward<_Args>(__args)...);
+ }
+
+ typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_;
+ typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_;
+
+ template<typename _Tp, typename... _Args>
+ void _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args)
+ {
+ auto& __outer = __outermost(*this);
+ typedef typename std::decay<decltype(__outer)>::type __outer_type;
+ typedef allocator_traits<__outer_type> __o_traits;
+ __o_traits::construct(__outer, __p, allocator_arg, inner_allocator(),
+ std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Tp, typename... _Args>
+ void _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args)
+ {
+ auto& __outer = __outermost(*this);
+ typedef typename std::decay<decltype(__outer)>::type __outer_type;
+ typedef allocator_traits<__outer_type> __o_traits;
+ __o_traits::construct(__outer, __p, std::forward<_Args>(__args)...,
+ inner_allocator());
+ }
+
+ template<typename _Alloc>
+ static _Alloc
+ _S_select_on_copy(const _Alloc& __a)
+ {
+ typedef allocator_traits<_Alloc> __a_traits;
+ return __a_traits::select_on_container_copy_construction(__a);
+ }
+
+ template<int... _Indices>
+ scoped_allocator_adaptor(tuple<const _OuterAlloc&,
+ const _InnerAllocs&...> __refs,
+ _Index_tuple<_Indices...>)
+ : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))),
+ _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...)
+ { }
+
+ public:
+ typedef _OuterAlloc outer_allocator_type;
+ typedef typename __inner_type::__type inner_allocator_type;
+
+ typedef typename __traits::value_type value_type;
+ typedef typename __traits::size_type size_type;
+ typedef typename __traits::difference_type difference_type;
+ typedef typename __traits::pointer pointer;
+ typedef typename __traits::const_pointer const_pointer;
+ typedef typename __traits::void_pointer void_pointer;
+ typedef typename __traits::const_void_pointer const_void_pointer;
+
+ typedef typename conditional<
+ __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value,
+ true_type, false_type>::type propagate_on_container_copy_assignment;
+ typedef typename conditional<
+ __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value,
+ true_type, false_type>::type propagate_on_container_move_assignment;
+ typedef typename conditional<
+ __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value,
+ true_type, false_type>::type propagate_on_container_swap;
+
+ template <class _Tp>
+ struct rebind
+ {
+ // TODO: use rebind_alloc<Tp> instead of __rebind_alloc<Tp>::__type
+ typedef scoped_allocator_adaptor<
+ typename __traits::template __rebind_alloc<_Tp>::__type,
+ _InnerAllocs...> other;
+ };
+
+ scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
+
+ template<typename _Outer2>
+ scoped_allocator_adaptor(_Outer2&& __outer,
+ const _InnerAllocs&... __inner)
+ : _OuterAlloc(std::forward<_Outer2>(__outer)),
+ _M_inner(__inner...)
+ { }
+
+ scoped_allocator_adaptor(const scoped_allocator_adaptor& __other)
+ : _OuterAlloc(__other.outer_allocator()),
+ _M_inner(__other._M_inner)
+ { }
+
+ scoped_allocator_adaptor(scoped_allocator_adaptor&& __other)
+ : _OuterAlloc(std::move(__other.outer_allocator())),
+ _M_inner(std::move(__other._M_inner))
+ { }
+
+ template<typename _Outer2>
+ scoped_allocator_adaptor(
+ const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other)
+ : _OuterAlloc(__other.outer_allocator()),
+ _M_inner(__other._M_inner)
+ { }
+
+ template<typename _Outer2>
+ scoped_allocator_adaptor(
+ scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other)
+ : _OuterAlloc(std::move(__other.outer_allocator())),
+ _M_inner(std::move(__other._M_inner))
+ { }
+
+ inner_allocator_type& inner_allocator() noexcept
+ { return _M_inner._M_get(this); }
+
+ const inner_allocator_type& inner_allocator() const noexcept
+ { return _M_inner._M_get(this); }
+
+ outer_allocator_type& outer_allocator() noexcept
+ { return static_cast<_OuterAlloc&>(*this); }
+
+ const outer_allocator_type& outer_allocator() const noexcept
+ { return static_cast<const _OuterAlloc&>(*this); }
+
+ pointer allocate(size_type __n)
+ { return __traits::allocate(outer_allocator(), __n); }
+
+ pointer allocate(size_type __n, const_void_pointer __hint)
+ { return __traits::allocate(outer_allocator(), __n, __hint); }
+
+ void deallocate(pointer __p, size_type __n)
+ { return __traits::deallocate(outer_allocator(), __p, __n); }
+
+ size_type max_size() const
+ { return __traits::max_size(outer_allocator()); }
+
+ template<typename _Tp, typename... _Args>
+ void construct(_Tp* __p, _Args&&... __args)
+ {
+ auto& __inner = inner_allocator();
+ auto __use_tag
+ = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
+ _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
+ }
+
+ // TODO: construct pairs
+
+ template<typename _Tp>
+ void destroy(_Tp* __p)
+ {
+ auto& __outer = __outermost(*this);
+ typedef typename std::decay<decltype(__outer)>::type __outer_type;
+ allocator_traits<__outer_type>::destroy(__outer, __p);
+ }
+
+ scoped_allocator_adaptor
+ select_on_container_copy_construction() const
+ {
+ typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type
+ _Indices;
+ return scoped_allocator_adaptor(_M_tie(), _Indices());
+ }
+
+ template <typename _OutA1, typename _OutA2, typename... _InA>
+ friend bool
+ operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+ const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept;
+ };
+
+ template <typename _OutA1, typename _OutA2, typename... _InA>
+ inline bool
+ operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+ const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
+ {
+ return __a.outer_allocator() == __b.outer_allocator()
+ && __a._M_inner == __b._M_inner;
+ }
+
+ template <typename _OutA1, typename _OutA2, typename... _InA>
+ inline bool
+ operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+ const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
+ { return !(__a == __b); }
+
+ /// @}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // __GXX_EXPERIMENTAL_CXX0X__
+
+#endif // _SCOPED_ALLOCATOR
Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 176078)
+++ include/Makefile.am (revision 176079)
@@ -58,6 +58,7 @@
${std_srcdir}/random \
${std_srcdir}/ratio \
${std_srcdir}/regex \
+ ${std_srcdir}/scoped_allocator \
${std_srcdir}/set \
${std_srcdir}/sstream \
${std_srcdir}/stack \
Index: ChangeLog
===================================================================
--- ChangeLog (revision 176078)
+++ ChangeLog (revision 176079)
@@ -1,5 +1,17 @@
2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com>
+ * include/Makefile.am: Add new header.
+ * include/Makefile.in: Regenerate.
+ * include/std/scoped_allocator: New.
+ * doc/xml/manual/status_cxx200x.xml: Update.
+ * testsuite/20_util/scoped_allocator/1.cc: New.
+ * testsuite/20_util/scoped_allocator/propagation.cc: New.
+ * testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
+ * testsuite/20_util/scoped_allocator/requirements/
+ explicit_instantiation.cc: New.
+
+2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com>
+
* include/bits/stl_vector.h: Use new allocator model in C++0x mode.
* include/bits/vector.tcc: Likewise.
* testsuite/util/testsuite_allocator.h (propagating_allocator): Define.
Index: testsuite/20_util/scoped_allocator/requirements/typedefs.cc
===================================================================
--- testsuite/20_util/scoped_allocator/requirements/typedefs.cc (revision 0)
+++ testsuite/20_util/scoped_allocator/requirements/typedefs.cc (revision 176079)
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing scoped_allocator with NO OTHER INCLUDES.
+
+#include <scoped_allocator>
+
+// { dg-do compile }
+
+template<typename T>
+ struct minimal_allocator
+ {
+ typedef T value_type;
+ minimal_allocator();
+ template <typename U>
+ minimal_allocator(const minimal_allocator<U>&);
+ T* allocate(unsigned long);
+ void deallocate(T*, unsigned long);
+ };
+
+struct S
+{
+ typedef minimal_allocator<short> allocator_type;
+ S(const allocator_type&);
+};
+
+void test01()
+{
+ typedef minimal_allocator<S> outer_type;
+ typedef minimal_allocator<S::allocator_type> inner_type;
+ typedef std::scoped_allocator_adaptor<outer_type, inner_type> test_type;
+
+ // Check for required typedefs
+ typedef typename test_type::outer_allocator_type outer_allocator_type;
+ typedef typename test_type::inner_allocator_type inner_allocator_type;
+ typedef typename test_type::value_type value_type;
+ typedef typename test_type::size_type size_type;
+ typedef typename test_type::difference_type difference_type;
+ typedef typename test_type::pointer pointer;
+ typedef typename test_type::const_pointer const_pointer;
+ typedef typename test_type::void_pointer void_pointer;
+ typedef typename test_type::const_void_pointer const_void_pointer;
+ typedef typename test_type::propagate_on_container_copy_assignment
+ propagate_on_container_copy_assignment;
+ typedef typename test_type::propagate_on_container_move_assignment
+ propagate_on_container_move_assignment;
+ typedef typename test_type::propagate_on_container_swap
+ propagate_on_container_swap;
+}
+
Index: testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc
===================================================================
--- testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc (revision 0)
+++ testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc (revision 176079)
@@ -0,0 +1,47 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing memory with NO OTHER INCLUDES.
+
+#include <scoped_allocator>
+#include <memory>
+
+typedef short test_type;
+
+template<typename T>
+ struct minimal_allocator
+ {
+ typedef T value_type;
+ minimal_allocator();
+ template <typename U>
+ minimal_allocator(const minimal_allocator<U>&);
+ T* allocate(unsigned long);
+ void deallocate(T*, unsigned long);
+ };
+
+namespace std
+{
+ template struct scoped_allocator_adaptor<std::allocator<test_type>>;
+
+ template struct scoped_allocator_adaptor<minimal_allocator<test_type>>;
+
+ template struct scoped_allocator_adaptor<std::allocator<test_type>,
+ minimal_allocator<test_type>>;
+}
Index: testsuite/20_util/scoped_allocator/1.cc
===================================================================
--- testsuite/20_util/scoped_allocator/1.cc (revision 0)
+++ testsuite/20_util/scoped_allocator/1.cc (revision 176079)
@@ -0,0 +1,99 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <scoped_allocator>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+struct Element
+{
+ typedef uneq_allocator<Element> allocator_type;
+
+ allocator_type alloc;
+
+ Element(const allocator_type& a = allocator_type()) : alloc(a) { }
+
+ Element(std::allocator_arg_t, const allocator_type& a, int i = 0)
+ : alloc(a) { }
+
+ Element(std::allocator_arg_t, const allocator_type& a, const Element&)
+ : alloc(a) { }
+
+ const allocator_type& get_allocator() const { return alloc; }
+};
+
+void test01()
+{
+ bool test __attribute((unused)) = false;
+
+ typedef std::scoped_allocator_adaptor<Element::allocator_type> alloc1_type;
+
+ typedef std::vector<Element, alloc1_type> EltVec;
+
+ alloc1_type a1(1);
+ Element e;
+ EltVec ev1(1, e, a1);
+ VERIFY( ev1[0].get_allocator().get_personality() == 1 );
+}
+
+void test02()
+{
+ bool test __attribute((unused)) = false;
+
+ typedef std::vector<Element, Element::allocator_type> EltVec;
+
+ typedef std::scoped_allocator_adaptor<EltVec::allocator_type,
+ Element::allocator_type> alloc_type;
+
+ typedef std::vector<EltVec, alloc_type> EltVecVec;
+
+ alloc_type a(1, 2);
+ Element e;
+ EltVec ev(1, e);
+ EltVecVec evv(1, ev, a);
+
+ VERIFY( evv.get_allocator().get_personality() == 1 );
+ VERIFY( evv[0].get_allocator().get_personality() == 2 );
+ VERIFY( evv[0][0].get_allocator().get_personality() == 2 );
+
+ alloc_type a2(3, 4);
+
+ EltVecVec evv2(evv, a2); // copy with a different allocator
+
+ VERIFY( evv2.get_allocator().get_personality() == 3 );
+ VERIFY( evv2[0].get_allocator().get_personality() == 4 );
+ VERIFY( evv2[0][0].get_allocator().get_personality() == 4 );
+
+ EltVecVec evv3(std::move(evv), a2); // move with a different allocator
+
+ VERIFY( evv3.get_allocator().get_personality() == 3 );
+ VERIFY( evv3[0].get_allocator().get_personality() == 4 );
+ VERIFY( evv3[0][0].get_allocator().get_personality() == 4 );
+
+}
+
+
+int main()
+{
+ test01();
+}
Index: testsuite/20_util/scoped_allocator/propagation.cc
===================================================================
--- testsuite/20_util/scoped_allocator/propagation.cc (revision 0)
+++ testsuite/20_util/scoped_allocator/propagation.cc (revision 176079)
@@ -0,0 +1,105 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// test that propagate_on_container_xxx is true iff it is true for
+// any of the outer or inner allocators
+
+#include <scoped_allocator>
+
+using std::scoped_allocator_adaptor;
+
+typedef short test_type;
+
+template<typename T>
+ struct minimal_allocator
+ {
+ typedef T value_type;
+ minimal_allocator();
+ template <typename U>
+ minimal_allocator(const minimal_allocator<U>&);
+ T* allocate(std::size_t);
+ void deallocate(T*, std::size_t);
+ };
+
+template<typename T, bool copy, bool move, bool swap>
+ struct test_allocator : minimal_allocator<T>
+ {
+ struct propagate_on_container_copy_assignment
+ { static const bool value = copy; };
+
+ struct propagate_on_container_move_assignment
+ { static const bool value = move; };
+
+ struct propagate_on_container_swap
+ { static const bool value = swap; };
+ };
+
+template<typename A>
+ constexpr bool prop_on_copy()
+ {
+ typedef typename A::propagate_on_container_copy_assignment type;
+ return type::value;
+ }
+
+template<typename A>
+ constexpr bool prop_on_move()
+ {
+ typedef typename A::propagate_on_container_move_assignment type;
+ return type::value;
+ }
+
+template<typename A>
+ constexpr bool prop_on_swap()
+ {
+ typedef typename A::propagate_on_container_swap type;
+ return type::value;
+ }
+
+template<typename A, bool C, bool M, bool S>
+ constexpr bool test1()
+ {
+ static_assert( prop_on_copy<A>() == C, "copy" );
+ static_assert( prop_on_move<A>() == M, "move" );
+ static_assert( prop_on_swap<A>() == S, "swap" );
+ return true;
+ }
+
+template<bool C, bool M, bool S>
+ constexpr bool test2()
+ {
+ typedef minimal_allocator<test_type> base_alloc;
+ typedef test_allocator<test_type, C, M, S> test_alloc;
+ typedef scoped_allocator_adaptor<base_alloc, test_alloc> scoped1;
+ typedef scoped_allocator_adaptor<test_alloc, base_alloc> scoped2;
+ typedef scoped_allocator_adaptor<test_alloc, test_alloc> scoped3;
+ return test1<scoped1, C, M, S>()
+ && test1<scoped2, C, M, S>()
+ && test1<scoped3, C, M, S>();
+ }
+
+static_assert( test2<false, false, false>(), "never propagate" );
+static_assert( test2<true, false, false>(), "propagate on copy" );
+static_assert( test2<false, true, false>(), "propagate on move" );
+static_assert( test2<false, false, true>(), "propagate on swap" );
+static_assert( test2<true, true, false>(), "propagate on copy & move" );
+static_assert( test2<true, false, true>(), "propagate on copy & swap" );
+static_assert( test2<false, true, true>(), "propagate on move & swap" );
+static_assert( test2<true, true, true>(), "always propagate" );
+
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [v3] add <scoped_allocator>
2011-07-18 17:08 ` Jonathan Wakely
@ 2011-07-20 15:55 ` Ed Smith-Rowland
2011-07-20 16:10 ` Paolo Carlini
0 siblings, 1 reply; 4+ messages in thread
From: Ed Smith-Rowland @ 2011-07-20 15:55 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1101 bytes --]
On 07/18/2011 12:18 PM, Jonathan Wakely wrote:
> On 9 July 2011 14:46, Jonathan Wakely wrote:
>> This adds the new<scoped_allocator> header. Currently only
>> std::vector has the necessary support for C++0x allocators to be
>> usable with std::scoped_allocator_adaptor.
>>
>> * include/Makefile.am: Add new header.
>> * include/Makefile.in: Regenerate.
>> * include/std/scoped_allocator: New.
>> * doc/xml/manual/status_cxx200x.xml: Update.
>> * testsuite/20_util/scoped_allocator/1.cc: New.
>> * testsuite/20_util/scoped_allocator/propagation.cc: New.
>> * testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
>> * testsuite/20_util/scoped_allocator/requirements/
>> explicit_instantiation.cc: New.
>>
>> Tested x86_64-linux, commited to trunkx
> Thanks to Francois for pointing out I attached the wrong patch, this
> is the patch matching the changelog above, in r176079
All,
Here is a trivial addition to include scoped_allocator in the
precompiled headers.
It bootstrapped and regtested on x86_64 linux.
Ed
[-- Attachment #2: CL --]
[-- Type: text/plain, Size: 108 bytes --]
2011-07-20 Ed Smith-Rowland <3dw4rd@verizon.net>
* include/precompiled/stdc++.h: Add scoped_allocator.
[-- Attachment #3: patch --]
[-- Type: text/plain, Size: 685 bytes --]
Index: include/precompiled/stdc++.h
===================================================================
--- include/precompiled/stdc++.h (revision 176462)
+++ include/precompiled/stdc++.h (working copy)
@@ -1,6 +1,6 @@
// C++ includes used for precompiling -*- C++ -*-
-// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -106,6 +106,7 @@
#include <random>
#include <ratio>
#include <regex>
+#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [v3] add <scoped_allocator>
2011-07-20 15:55 ` Ed Smith-Rowland
@ 2011-07-20 16:10 ` Paolo Carlini
0 siblings, 0 replies; 4+ messages in thread
From: Paolo Carlini @ 2011-07-20 16:10 UTC (permalink / raw)
To: Ed Smith-Rowland; +Cc: Jonathan Wakely, libstdc++, gcc-patches
On 07/20/2011 05:34 PM, Ed Smith-Rowland wrote:
>
> Here is a trivial addition to include scoped_allocator in the
> precompiled headers. It bootstrapped and regtested on x86_64 linux.
Applied, thanks.
Paolo.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-07-20 15:47 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-09 14:44 [v3] add <scoped_allocator> Jonathan Wakely
2011-07-18 17:08 ` Jonathan Wakely
2011-07-20 15:55 ` Ed Smith-Rowland
2011-07-20 16:10 ` Paolo Carlini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).