mirror of git://gcc.gnu.org/git/gcc.git
Make std::deque meet C++11 allocator requirements.
* include/bits/deque.tcc (deque::operator=(const deque&)): Handle allocator propagation. (deque::emplace_front, deque::emplace_back): Use allocator traits. (deque::_M_push_back_aux, deque::_M_push_front_aux): Likewise. (deque::_M_pop_back_aux, deque::_M_pop_front_aux): Likewise. * include/bits/stl_deque.h (__deque_buf_size): Add constexpr. (_Deque_iterator): Handle allocators with custom pointers. (_Deque_base): Likewise. Use allocator traits. (deque): Likewise. Add allocator-extended constructors. (deque::_M_move_assign1, deque::_M_move_assign2): Implement move assignment via tag dispatching. (deque::_M_replace_map): Replace existing data. * include/debug/deque (deque): Add allocator-extended constructors. * include/profile/deque (deque): Likewise. * testsuite/23_containers/deque/allocator/copy.cc: New. * testsuite/23_containers/deque/allocator/copy_assign.cc: New. * testsuite/23_containers/deque/allocator/ext_ptr.cc: New. * testsuite/23_containers/deque/allocator/minimal.cc: New. * testsuite/23_containers/deque/allocator/move.cc: New. * testsuite/23_containers/deque/allocator/move_assign-2.cc: New. * testsuite/23_containers/deque/allocator/move_assign.cc: New. * testsuite/23_containers/deque/allocator/noexcept.cc: New. * testsuite/23_containers/deque/allocator/swap.cc: New. * testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Adjust dg-error line number. * testsuite/23_containers/deque/requirements/dr438/ constructor_1_neg.cc: Likewise. * testsuite/23_containers/deque/requirements/dr438/ constructor_2_neg.cc: Likewise. * testsuite/23_containers/deque/requirements/dr438/insert_neg.cc: Likewise. * testsuite/23_containers/vector/52591.cc: Test both the propagating and always-equal cases. From-SVN: r215090
This commit is contained in:
parent
e8a54173bc
commit
fd18c76ac8
|
|
@ -1,3 +1,39 @@
|
||||||
|
2014-09-09 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
* include/bits/deque.tcc (deque::operator=(const deque&)): Handle
|
||||||
|
allocator propagation.
|
||||||
|
(deque::emplace_front, deque::emplace_back): Use allocator traits.
|
||||||
|
(deque::_M_push_back_aux, deque::_M_push_front_aux): Likewise.
|
||||||
|
(deque::_M_pop_back_aux, deque::_M_pop_front_aux): Likewise.
|
||||||
|
* include/bits/stl_deque.h (__deque_buf_size): Add constexpr.
|
||||||
|
(_Deque_iterator): Handle allocators with custom pointers.
|
||||||
|
(_Deque_base): Likewise. Use allocator traits.
|
||||||
|
(deque): Likewise. Add allocator-extended constructors.
|
||||||
|
(deque::_M_move_assign1, deque::_M_move_assign2): Implement move
|
||||||
|
assignment via tag dispatching.
|
||||||
|
(deque::_M_replace_map): Replace existing data.
|
||||||
|
* include/debug/deque (deque): Add allocator-extended constructors.
|
||||||
|
* include/profile/deque (deque): Likewise.
|
||||||
|
* testsuite/23_containers/deque/allocator/copy.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/copy_assign.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/ext_ptr.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/minimal.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/move.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/move_assign-2.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/move_assign.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/noexcept.cc: New.
|
||||||
|
* testsuite/23_containers/deque/allocator/swap.cc: New.
|
||||||
|
* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc:
|
||||||
|
Adjust dg-error line number.
|
||||||
|
* testsuite/23_containers/deque/requirements/dr438/
|
||||||
|
constructor_1_neg.cc: Likewise.
|
||||||
|
* testsuite/23_containers/deque/requirements/dr438/
|
||||||
|
constructor_2_neg.cc: Likewise.
|
||||||
|
* testsuite/23_containers/deque/requirements/dr438/insert_neg.cc:
|
||||||
|
Likewise.
|
||||||
|
* testsuite/23_containers/vector/52591.cc: Test both the propagating
|
||||||
|
and always-equal cases.
|
||||||
|
|
||||||
2014-09-06 François Dumont <fdumont@gcc.gnu.org>
|
2014-09-06 François Dumont <fdumont@gcc.gnu.org>
|
||||||
|
|
||||||
* include/bits/hashtable_policy.h (_Prime_rehash_policy): Constructor
|
* include/bits/hashtable_policy.h (_Prime_rehash_policy): Constructor
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
deque<_Tp, _Alloc>::
|
deque<_Tp, _Alloc>::
|
||||||
operator=(const deque& __x)
|
operator=(const deque& __x)
|
||||||
{
|
{
|
||||||
const size_type __len = size();
|
|
||||||
if (&__x != this)
|
if (&__x != this)
|
||||||
{
|
{
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
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,
|
||||||
|
// so deallocate everything and take copy of __x's data.
|
||||||
|
_M_replace_map(__x, __x.get_allocator());
|
||||||
|
std::__alloc_on_copy(_M_get_Tp_allocator(),
|
||||||
|
__x._M_get_Tp_allocator());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
std::__alloc_on_copy(_M_get_Tp_allocator(),
|
||||||
|
__x._M_get_Tp_allocator());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
const size_type __len = size();
|
||||||
if (__len >= __x.size())
|
if (__len >= __x.size())
|
||||||
_M_erase_at_end(std::copy(__x.begin(), __x.end(),
|
_M_erase_at_end(std::copy(__x.begin(), __x.end(),
|
||||||
this->_M_impl._M_start));
|
this->_M_impl._M_start));
|
||||||
|
|
@ -117,8 +134,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
{
|
{
|
||||||
if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
|
if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
|
||||||
{
|
{
|
||||||
this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1,
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
std::forward<_Args>(__args)...);
|
this->_M_impl._M_start._M_cur - 1,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
--this->_M_impl._M_start._M_cur;
|
--this->_M_impl._M_start._M_cur;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -134,8 +152,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
if (this->_M_impl._M_finish._M_cur
|
if (this->_M_impl._M_finish._M_cur
|
||||||
!= this->_M_impl._M_finish._M_last - 1)
|
!= this->_M_impl._M_finish._M_last - 1)
|
||||||
{
|
{
|
||||||
this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
std::forward<_Args>(__args)...);
|
this->_M_impl._M_finish._M_cur,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
++this->_M_impl._M_finish._M_cur;
|
++this->_M_impl._M_finish._M_cur;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -453,8 +472,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
std::forward<_Args>(__args)...);
|
this->_M_impl._M_finish._M_cur,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
#else
|
#else
|
||||||
this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
|
this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -490,8 +510,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
- 1);
|
- 1);
|
||||||
this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
|
this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
this->_M_impl.construct(this->_M_impl._M_start._M_cur,
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
std::forward<_Args>(__args)...);
|
this->_M_impl._M_start._M_cur,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
#else
|
#else
|
||||||
this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
|
this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -512,7 +533,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
_M_deallocate_node(this->_M_impl._M_finish._M_first);
|
_M_deallocate_node(this->_M_impl._M_finish._M_first);
|
||||||
this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
|
this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
|
||||||
this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
|
this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
|
||||||
this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
|
_Alloc_traits::destroy(_M_get_Tp_allocator(),
|
||||||
|
this->_M_impl._M_finish._M_cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
|
// Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
|
||||||
|
|
@ -524,7 +546,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
void deque<_Tp, _Alloc>::
|
void deque<_Tp, _Alloc>::
|
||||||
_M_pop_front_aux()
|
_M_pop_front_aux()
|
||||||
{
|
{
|
||||||
this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
|
_Alloc_traits::destroy(_M_get_Tp_allocator(),
|
||||||
|
this->_M_impl._M_start._M_cur);
|
||||||
_M_deallocate_node(this->_M_impl._M_start._M_first);
|
_M_deallocate_node(this->_M_impl._M_start._M_first);
|
||||||
this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
|
this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
|
||||||
this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
|
this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
#define _GLIBCXX_DEQUE_BUF_SIZE 512
|
#define _GLIBCXX_DEQUE_BUF_SIZE 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline size_t
|
_GLIBCXX_CONSTEXPR inline size_t
|
||||||
__deque_buf_size(size_t __size)
|
__deque_buf_size(size_t __size)
|
||||||
{ return (__size < _GLIBCXX_DEQUE_BUF_SIZE
|
{ return (__size < _GLIBCXX_DEQUE_BUF_SIZE
|
||||||
? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); }
|
? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); }
|
||||||
|
|
@ -105,8 +105,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
template<typename _Tp, typename _Ref, typename _Ptr>
|
template<typename _Tp, typename _Ref, typename _Ptr>
|
||||||
struct _Deque_iterator
|
struct _Deque_iterator
|
||||||
{
|
{
|
||||||
|
#if __cplusplus < 201103L
|
||||||
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
|
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
|
||||||
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
|
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
|
||||||
|
typedef _Tp* _Elt_pointer;
|
||||||
|
typedef _Tp** _Map_pointer;
|
||||||
|
#else
|
||||||
|
private:
|
||||||
|
template<typename _Up>
|
||||||
|
using __ptr_to = typename pointer_traits<_Ptr>::template rebind<_Up>;
|
||||||
|
template<typename _CvTp>
|
||||||
|
using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_to<_CvTp>>;
|
||||||
|
public:
|
||||||
|
typedef __iter<_Tp> iterator;
|
||||||
|
typedef __iter<const _Tp> const_iterator;
|
||||||
|
typedef __ptr_to<_Tp> _Elt_pointer;
|
||||||
|
typedef __ptr_to<_Elt_pointer> _Map_pointer;
|
||||||
|
#endif
|
||||||
|
|
||||||
static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
|
static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
|
||||||
{ return __deque_buf_size(sizeof(_Tp)); }
|
{ return __deque_buf_size(sizeof(_Tp)); }
|
||||||
|
|
@ -117,20 +132,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
typedef _Ref reference;
|
typedef _Ref reference;
|
||||||
typedef size_t size_type;
|
typedef size_t size_type;
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
typedef _Tp** _Map_pointer;
|
|
||||||
typedef _Deque_iterator _Self;
|
typedef _Deque_iterator _Self;
|
||||||
|
|
||||||
_Tp* _M_cur;
|
_Elt_pointer _M_cur;
|
||||||
_Tp* _M_first;
|
_Elt_pointer _M_first;
|
||||||
_Tp* _M_last;
|
_Elt_pointer _M_last;
|
||||||
_Map_pointer _M_node;
|
_Map_pointer _M_node;
|
||||||
|
|
||||||
_Deque_iterator(_Tp* __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT
|
_Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT
|
||||||
: _M_cur(__x), _M_first(*__y),
|
: _M_cur(__x), _M_first(*__y),
|
||||||
_M_last(*__y + _S_buffer_size()), _M_node(__y) { }
|
_M_last(*__y + _S_buffer_size()), _M_node(__y) { }
|
||||||
|
|
||||||
_Deque_iterator() _GLIBCXX_NOEXCEPT
|
_Deque_iterator() _GLIBCXX_NOEXCEPT
|
||||||
: _M_cur(0), _M_first(0), _M_last(0), _M_node(0) { }
|
: _M_cur(), _M_first(), _M_last(), _M_node() { }
|
||||||
|
|
||||||
_Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
|
_Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
|
||||||
: _M_cur(__x._M_cur), _M_first(__x._M_first),
|
: _M_cur(__x._M_cur), _M_first(__x._M_first),
|
||||||
|
|
@ -443,15 +457,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
template<typename _Tp, typename _Alloc>
|
template<typename _Tp, typename _Alloc>
|
||||||
class _Deque_base
|
class _Deque_base
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
|
||||||
|
rebind<_Tp>::other _Tp_alloc_type;
|
||||||
|
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits;
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
typedef _Tp* _Ptr;
|
||||||
|
typedef const _Tp* _Ptr_const;
|
||||||
|
#else
|
||||||
|
typedef typename _Alloc_traits::pointer _Ptr;
|
||||||
|
typedef typename _Alloc_traits::const_pointer _Ptr_const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef typename _Alloc_traits::template rebind<_Ptr>::other
|
||||||
|
_Map_alloc_type;
|
||||||
|
typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Alloc allocator_type;
|
typedef _Alloc allocator_type;
|
||||||
|
typedef typename _Alloc_traits::size_type size_type;
|
||||||
|
|
||||||
allocator_type
|
allocator_type
|
||||||
get_allocator() const _GLIBCXX_NOEXCEPT
|
get_allocator() const _GLIBCXX_NOEXCEPT
|
||||||
{ return allocator_type(_M_get_Tp_allocator()); }
|
{ return allocator_type(_M_get_Tp_allocator()); }
|
||||||
|
|
||||||
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
|
typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator;
|
||||||
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
|
typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator;
|
||||||
|
|
||||||
_Deque_base()
|
_Deque_base()
|
||||||
: _M_impl()
|
: _M_impl()
|
||||||
|
|
@ -467,19 +499,43 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
|
|
||||||
_Deque_base(const allocator_type& __a)
|
_Deque_base(const allocator_type& __a)
|
||||||
: _M_impl(__a)
|
: _M_impl(__a)
|
||||||
{ }
|
{ /* Caller must initialize map. */ }
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
_Deque_base(_Deque_base&& __x)
|
_Deque_base(_Deque_base&& __x)
|
||||||
: _M_impl(std::move(__x._M_get_Tp_allocator()))
|
: _M_impl(std::move(__x._M_get_Tp_allocator()))
|
||||||
{
|
{
|
||||||
_M_initialize_map(0);
|
|
||||||
if (__x._M_impl._M_map)
|
if (__x._M_impl._M_map)
|
||||||
{
|
{
|
||||||
std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
|
this->_M_impl._M_swap_data(__x._M_impl);
|
||||||
std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
|
__try
|
||||||
std::swap(this->_M_impl._M_map, __x._M_impl._M_map);
|
{
|
||||||
std::swap(this->_M_impl._M_map_size, __x._M_impl._M_map_size);
|
// Re-initialize __x using its moved-from allocator.
|
||||||
|
__x._M_initialize_map(0);
|
||||||
|
}
|
||||||
|
__catch (...)
|
||||||
|
{
|
||||||
|
this->_M_impl._M_swap_data(__x._M_impl);
|
||||||
|
__x._M_get_Tp_allocator() = std::move(_M_get_Tp_allocator());
|
||||||
|
__throw_exception_again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n)
|
||||||
|
: _M_impl(__a)
|
||||||
|
{
|
||||||
|
if (__x.get_allocator() == __a)
|
||||||
|
{
|
||||||
|
if (__x._M_impl._M_map)
|
||||||
|
{
|
||||||
|
_M_initialize_map(0);
|
||||||
|
this->_M_impl._M_swap_data(__x._M_impl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_M_initialize_map(__n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -487,9 +543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
~_Deque_base() _GLIBCXX_NOEXCEPT;
|
~_Deque_base() _GLIBCXX_NOEXCEPT;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef typename _Alloc::template rebind<_Tp*>::other _Map_alloc_type;
|
typedef typename iterator::_Map_pointer _Map_pointer;
|
||||||
|
|
||||||
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
|
|
||||||
|
|
||||||
//This struct encapsulates the implementation of the std::deque
|
//This struct encapsulates the implementation of the std::deque
|
||||||
//standard container and at the same time makes use of the EBO
|
//standard container and at the same time makes use of the EBO
|
||||||
|
|
@ -497,27 +551,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
struct _Deque_impl
|
struct _Deque_impl
|
||||||
: public _Tp_alloc_type
|
: public _Tp_alloc_type
|
||||||
{
|
{
|
||||||
_Tp** _M_map;
|
_Map_pointer _M_map;
|
||||||
size_t _M_map_size;
|
size_t _M_map_size;
|
||||||
iterator _M_start;
|
iterator _M_start;
|
||||||
iterator _M_finish;
|
iterator _M_finish;
|
||||||
|
|
||||||
_Deque_impl()
|
_Deque_impl()
|
||||||
: _Tp_alloc_type(), _M_map(0), _M_map_size(0),
|
: _Tp_alloc_type(), _M_map(), _M_map_size(0),
|
||||||
_M_start(), _M_finish()
|
_M_start(), _M_finish()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
_Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
|
_Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
|
||||||
: _Tp_alloc_type(__a), _M_map(0), _M_map_size(0),
|
: _Tp_alloc_type(__a), _M_map(), _M_map_size(0),
|
||||||
_M_start(), _M_finish()
|
_M_start(), _M_finish()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
_Deque_impl(_Tp_alloc_type&& __a) _GLIBCXX_NOEXCEPT
|
_Deque_impl(_Tp_alloc_type&& __a) _GLIBCXX_NOEXCEPT
|
||||||
: _Tp_alloc_type(std::move(__a)), _M_map(0), _M_map_size(0),
|
: _Tp_alloc_type(std::move(__a)), _M_map(), _M_map_size(0),
|
||||||
_M_start(), _M_finish()
|
_M_start(), _M_finish()
|
||||||
{ }
|
{ }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void _M_swap_data(_Deque_impl& __x)
|
||||||
|
{
|
||||||
|
std::swap(this->_M_start, __x._M_start);
|
||||||
|
std::swap(this->_M_finish, __x._M_finish);
|
||||||
|
std::swap(this->_M_map, __x._M_map);
|
||||||
|
std::swap(this->_M_map_size, __x._M_map_size);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_Tp_alloc_type&
|
_Tp_alloc_type&
|
||||||
|
|
@ -532,30 +594,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
_M_get_map_allocator() const _GLIBCXX_NOEXCEPT
|
_M_get_map_allocator() const _GLIBCXX_NOEXCEPT
|
||||||
{ return _Map_alloc_type(_M_get_Tp_allocator()); }
|
{ return _Map_alloc_type(_M_get_Tp_allocator()); }
|
||||||
|
|
||||||
_Tp*
|
_Ptr
|
||||||
_M_allocate_node()
|
_M_allocate_node()
|
||||||
{
|
{
|
||||||
return _M_impl._Tp_alloc_type::allocate(__deque_buf_size(sizeof(_Tp)));
|
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits;
|
||||||
|
return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_M_deallocate_node(_Tp* __p) _GLIBCXX_NOEXCEPT
|
_M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT
|
||||||
{
|
{
|
||||||
_M_impl._Tp_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp)));
|
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits;
|
||||||
|
_Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_Tp**
|
_Map_pointer
|
||||||
_M_allocate_map(size_t __n)
|
_M_allocate_map(size_t __n)
|
||||||
{ return _M_get_map_allocator().allocate(__n); }
|
{
|
||||||
|
_Map_alloc_type __map_alloc = _M_get_map_allocator();
|
||||||
|
return _Map_alloc_traits::allocate(__map_alloc, __n);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_M_deallocate_map(_Tp** __p, size_t __n) _GLIBCXX_NOEXCEPT
|
_M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT
|
||||||
{ _M_get_map_allocator().deallocate(__p, __n); }
|
{
|
||||||
|
_Map_alloc_type __map_alloc = _M_get_map_allocator();
|
||||||
|
_Map_alloc_traits::deallocate(__map_alloc, __p, __n);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _M_initialize_map(size_t);
|
void _M_initialize_map(size_t);
|
||||||
void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
|
void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish);
|
||||||
void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT;
|
void _M_destroy_nodes(_Map_pointer __nstart,
|
||||||
|
_Map_pointer __nfinish) _GLIBCXX_NOEXCEPT;
|
||||||
enum { _S_initial_map_size = 8 };
|
enum { _S_initial_map_size = 8 };
|
||||||
|
|
||||||
_Deque_impl _M_impl;
|
_Deque_impl _M_impl;
|
||||||
|
|
@ -576,7 +647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
/**
|
/**
|
||||||
* @brief Layout storage.
|
* @brief Layout storage.
|
||||||
* @param __num_elements The count of T's for which to allocate space
|
* @param __num_elements The count of T's for which to allocate space
|
||||||
* at first.
|
* at first.
|
||||||
* @return Nothing.
|
* @return Nothing.
|
||||||
*
|
*
|
||||||
* The initial underlying memory layout is a bit complicated...
|
* The initial underlying memory layout is a bit complicated...
|
||||||
|
|
@ -598,16 +669,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
// the beginning of _M_map, but for small maps it may be as far in as
|
// the beginning of _M_map, but for small maps it may be as far in as
|
||||||
// _M_map+3.
|
// _M_map+3.
|
||||||
|
|
||||||
_Tp** __nstart = (this->_M_impl._M_map
|
_Map_pointer __nstart = (this->_M_impl._M_map
|
||||||
+ (this->_M_impl._M_map_size - __num_nodes) / 2);
|
+ (this->_M_impl._M_map_size - __num_nodes) / 2);
|
||||||
_Tp** __nfinish = __nstart + __num_nodes;
|
_Map_pointer __nfinish = __nstart + __num_nodes;
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{ _M_create_nodes(__nstart, __nfinish); }
|
{ _M_create_nodes(__nstart, __nfinish); }
|
||||||
__catch(...)
|
__catch(...)
|
||||||
{
|
{
|
||||||
_M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
|
_M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
|
||||||
this->_M_impl._M_map = 0;
|
this->_M_impl._M_map = _Map_pointer();
|
||||||
this->_M_impl._M_map_size = 0;
|
this->_M_impl._M_map_size = 0;
|
||||||
__throw_exception_again;
|
__throw_exception_again;
|
||||||
}
|
}
|
||||||
|
|
@ -623,9 +694,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
template<typename _Tp, typename _Alloc>
|
template<typename _Tp, typename _Alloc>
|
||||||
void
|
void
|
||||||
_Deque_base<_Tp, _Alloc>::
|
_Deque_base<_Tp, _Alloc>::
|
||||||
_M_create_nodes(_Tp** __nstart, _Tp** __nfinish)
|
_M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish)
|
||||||
{
|
{
|
||||||
_Tp** __cur;
|
_Map_pointer __cur;
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
for (__cur = __nstart; __cur < __nfinish; ++__cur)
|
for (__cur = __nstart; __cur < __nfinish; ++__cur)
|
||||||
|
|
@ -641,9 +712,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
template<typename _Tp, typename _Alloc>
|
template<typename _Tp, typename _Alloc>
|
||||||
void
|
void
|
||||||
_Deque_base<_Tp, _Alloc>::
|
_Deque_base<_Tp, _Alloc>::
|
||||||
_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT
|
_M_destroy_nodes(_Map_pointer __nstart,
|
||||||
|
_Map_pointer __nfinish) _GLIBCXX_NOEXCEPT
|
||||||
{
|
{
|
||||||
for (_Tp** __n = __nstart; __n < __nfinish; ++__n)
|
for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n)
|
||||||
_M_deallocate_node(*__n);
|
_M_deallocate_node(*__n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,15 +811,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
|
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
|
||||||
__glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
|
__glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
|
||||||
|
|
||||||
typedef _Deque_base<_Tp, _Alloc> _Base;
|
typedef _Deque_base<_Tp, _Alloc> _Base;
|
||||||
typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
|
typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
|
||||||
|
typedef typename _Base::_Alloc_traits _Alloc_traits;
|
||||||
|
typedef typename _Base::_Map_pointer _Map_pointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Tp value_type;
|
typedef _Tp value_type;
|
||||||
typedef typename _Tp_alloc_type::pointer pointer;
|
typedef typename _Alloc_traits::pointer pointer;
|
||||||
typedef typename _Tp_alloc_type::const_pointer const_pointer;
|
typedef typename _Alloc_traits::const_pointer const_pointer;
|
||||||
typedef typename _Tp_alloc_type::reference reference;
|
typedef typename _Alloc_traits::reference reference;
|
||||||
typedef typename _Tp_alloc_type::const_reference const_reference;
|
typedef typename _Alloc_traits::const_reference const_reference;
|
||||||
typedef typename _Base::iterator iterator;
|
typedef typename _Base::iterator iterator;
|
||||||
typedef typename _Base::const_iterator const_iterator;
|
typedef typename _Base::const_iterator const_iterator;
|
||||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
@ -757,8 +831,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
typedef _Alloc allocator_type;
|
typedef _Alloc allocator_type;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef pointer* _Map_pointer;
|
|
||||||
|
|
||||||
static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
|
static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
|
||||||
{ return __deque_buf_size(sizeof(_Tp)); }
|
{ return __deque_buf_size(sizeof(_Tp)); }
|
||||||
|
|
||||||
|
|
@ -804,8 +876,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* constructed elements.
|
* constructed elements.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
deque(size_type __n)
|
deque(size_type __n, const allocator_type& __a = allocator_type())
|
||||||
: _Base(__n)
|
: _Base(__a, __n)
|
||||||
{ _M_default_initialize(); }
|
{ _M_default_initialize(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -844,7 +916,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* by @a __x.
|
* by @a __x.
|
||||||
*/
|
*/
|
||||||
deque(const deque& __x)
|
deque(const deque& __x)
|
||||||
: _Base(__x._M_get_Tp_allocator(), __x.size())
|
: _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()),
|
||||||
|
__x.size())
|
||||||
{ std::__uninitialized_copy_a(__x.begin(), __x.end(),
|
{ std::__uninitialized_copy_a(__x.begin(), __x.end(),
|
||||||
this->_M_impl._M_start,
|
this->_M_impl._M_start,
|
||||||
_M_get_Tp_allocator()); }
|
_M_get_Tp_allocator()); }
|
||||||
|
|
@ -860,6 +933,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
deque(deque&& __x)
|
deque(deque&& __x)
|
||||||
: _Base(std::move(__x)) { }
|
: _Base(std::move(__x)) { }
|
||||||
|
|
||||||
|
/// Copy constructor with alternative allocator
|
||||||
|
deque(const deque& __x, const allocator_type& __a)
|
||||||
|
: _Base(__a, __x.size())
|
||||||
|
{ std::__uninitialized_copy_a(__x.begin(), __x.end(),
|
||||||
|
this->_M_impl._M_start,
|
||||||
|
_M_get_Tp_allocator()); }
|
||||||
|
|
||||||
|
/// Move constructor with alternative allocator
|
||||||
|
deque(deque&& __x, const allocator_type& __a)
|
||||||
|
: _Base(std::move(__x), __a, __x.size())
|
||||||
|
{
|
||||||
|
if (__x.get_allocator() != __a)
|
||||||
|
{
|
||||||
|
std::__uninitialized_move_a(__x.begin(), __x.end(),
|
||||||
|
this->_M_impl._M_start,
|
||||||
|
_M_get_Tp_allocator());
|
||||||
|
__x.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Builds a %deque from an initializer list.
|
* @brief Builds a %deque from an initializer list.
|
||||||
* @param __l An initializer_list.
|
* @param __l An initializer_list.
|
||||||
|
|
@ -919,7 +1012,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* themselves are pointers, the pointed-to memory is not touched in any
|
* themselves are pointers, the pointed-to memory is not touched in any
|
||||||
* way. Managing the pointer is the user's responsibility.
|
* way. Managing the pointer is the user's responsibility.
|
||||||
*/
|
*/
|
||||||
~deque() _GLIBCXX_NOEXCEPT
|
~deque()
|
||||||
{ _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); }
|
{ _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -937,16 +1030,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* @brief %Deque move assignment operator.
|
* @brief %Deque move assignment operator.
|
||||||
* @param __x A %deque of identical element and allocator types.
|
* @param __x A %deque of identical element and allocator types.
|
||||||
*
|
*
|
||||||
* The contents of @a __x are moved into this deque (without copying).
|
* The contents of @a __x are moved into this deque (without copying,
|
||||||
|
* if the allocators permit it).
|
||||||
* @a __x is a valid, but unspecified %deque.
|
* @a __x is a valid, but unspecified %deque.
|
||||||
*/
|
*/
|
||||||
deque&
|
deque&
|
||||||
operator=(deque&& __x) noexcept
|
operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal())
|
||||||
{
|
{
|
||||||
// NB: DR 1204.
|
constexpr bool __always_equal = _Alloc_traits::_S_always_equal();
|
||||||
// NB: DR 675.
|
_M_move_assign1(std::move(__x),
|
||||||
this->clear();
|
integral_constant<bool, __always_equal>());
|
||||||
this->swap(__x);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1150,7 +1243,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
/** Returns the size() of the largest possible %deque. */
|
/** Returns the size() of the largest possible %deque. */
|
||||||
size_type
|
size_type
|
||||||
max_size() const _GLIBCXX_NOEXCEPT
|
max_size() const _GLIBCXX_NOEXCEPT
|
||||||
{ return _M_get_Tp_allocator().max_size(); }
|
{ return _Alloc_traits::max_size(_M_get_Tp_allocator()); }
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
/**
|
/**
|
||||||
|
|
@ -1368,7 +1461,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
{
|
{
|
||||||
if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
|
if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
|
||||||
{
|
{
|
||||||
this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1, __x);
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
|
this->_M_impl._M_start._M_cur - 1,
|
||||||
|
__x);
|
||||||
--this->_M_impl._M_start._M_cur;
|
--this->_M_impl._M_start._M_cur;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1400,7 +1495,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
if (this->_M_impl._M_finish._M_cur
|
if (this->_M_impl._M_finish._M_cur
|
||||||
!= this->_M_impl._M_finish._M_last - 1)
|
!= this->_M_impl._M_finish._M_last - 1)
|
||||||
{
|
{
|
||||||
this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __x);
|
_Alloc_traits::construct(this->_M_impl,
|
||||||
|
this->_M_impl._M_finish._M_cur, __x);
|
||||||
++this->_M_impl._M_finish._M_cur;
|
++this->_M_impl._M_finish._M_cur;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1431,7 +1527,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
if (this->_M_impl._M_start._M_cur
|
if (this->_M_impl._M_start._M_cur
|
||||||
!= this->_M_impl._M_start._M_last - 1)
|
!= this->_M_impl._M_start._M_last - 1)
|
||||||
{
|
{
|
||||||
this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
|
_Alloc_traits::destroy(this->_M_impl,
|
||||||
|
this->_M_impl._M_start._M_cur);
|
||||||
++this->_M_impl._M_start._M_cur;
|
++this->_M_impl._M_start._M_cur;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1453,7 +1550,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
!= this->_M_impl._M_finish._M_first)
|
!= this->_M_impl._M_finish._M_first)
|
||||||
{
|
{
|
||||||
--this->_M_impl._M_finish._M_cur;
|
--this->_M_impl._M_finish._M_cur;
|
||||||
this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
|
_Alloc_traits::destroy(this->_M_impl,
|
||||||
|
this->_M_impl._M_finish._M_cur);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_M_pop_back_aux();
|
_M_pop_back_aux();
|
||||||
|
|
@ -1659,17 +1757,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
* std::swap(d1,d2) will feed to this function.
|
* std::swap(d1,d2) will feed to this function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
swap(deque& __x) _GLIBCXX_NOEXCEPT
|
swap(deque& __x)
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
noexcept(_Alloc_traits::_S_nothrow_swap())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
|
_M_impl._M_swap_data(__x._M_impl);
|
||||||
std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
|
_Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),
|
||||||
std::swap(this->_M_impl._M_map, __x._M_impl._M_map);
|
__x._M_get_Tp_allocator());
|
||||||
std::swap(this->_M_impl._M_map_size, __x._M_impl._M_map_size);
|
|
||||||
|
|
||||||
// _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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -2011,6 +2106,79 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||||
void
|
void
|
||||||
_M_reallocate_map(size_type __nodes_to_add, bool __add_at_front);
|
_M_reallocate_map(size_type __nodes_to_add, bool __add_at_front);
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
// Constant-time, nothrow move assignment when source object's memory
|
||||||
|
// can be moved because the allocators are equal.
|
||||||
|
void
|
||||||
|
_M_move_assign1(deque&& __x, /* always equal: */ true_type) noexcept
|
||||||
|
{
|
||||||
|
this->_M_impl._M_swap_data(__x._M_impl);
|
||||||
|
__x.clear();
|
||||||
|
std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_M_move_assign1(deque&& __x, /* always equal: */ false_type)
|
||||||
|
{
|
||||||
|
constexpr bool __move_storage =
|
||||||
|
_Alloc_traits::_S_propagate_on_move_assign();
|
||||||
|
_M_move_assign2(std::move(__x),
|
||||||
|
integral_constant<bool, __move_storage>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy all elements and deallocate all memory, then replace
|
||||||
|
// with elements created from __args.
|
||||||
|
template<typename... _Args>
|
||||||
|
void
|
||||||
|
_M_replace_map(_Args&&... __args)
|
||||||
|
{
|
||||||
|
// Create new data first, so if allocation fails there are no effects.
|
||||||
|
deque __newobj(std::forward<_Args>(__args)...);
|
||||||
|
// Free existing storage using existing allocator.
|
||||||
|
clear();
|
||||||
|
_M_deallocate_node(*begin()._M_node); // one node left after clear()
|
||||||
|
_M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
|
||||||
|
this->_M_impl._M_map = nullptr;
|
||||||
|
this->_M_impl._M_map_size = 0;
|
||||||
|
// Take ownership of replacement memory.
|
||||||
|
this->_M_impl._M_swap_data(__newobj._M_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do move assignment when the allocator propagates.
|
||||||
|
void
|
||||||
|
_M_move_assign2(deque&& __x, /* propagate: */ true_type)
|
||||||
|
{
|
||||||
|
// Make a copy of the original allocator state.
|
||||||
|
auto __alloc = __x._M_get_Tp_allocator();
|
||||||
|
// The allocator propagates so storage can be moved from __x,
|
||||||
|
// leaving __x in a valid empty state with a moved-from allocator.
|
||||||
|
_M_replace_map(std::move(__x));
|
||||||
|
// Move the corresponding allocator state too.
|
||||||
|
_M_get_Tp_allocator() = std::move(__alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do move assignment when it may not be possible to move source
|
||||||
|
// object's memory, resulting in a linear-time operation.
|
||||||
|
void
|
||||||
|
_M_move_assign2(deque&& __x, /* propagate: */ false_type)
|
||||||
|
{
|
||||||
|
if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
|
||||||
|
{
|
||||||
|
// The allocators are equal so storage can be moved from __x,
|
||||||
|
// leaving __x in a valid empty state with its current allocator.
|
||||||
|
_M_replace_map(std::move(__x), __x.get_allocator());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The rvalue's allocator cannot be moved and 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,12 @@ namespace __debug
|
||||||
deque(const deque&) = default;
|
deque(const deque&) = default;
|
||||||
deque(deque&&) = default;
|
deque(deque&&) = default;
|
||||||
|
|
||||||
|
deque(const deque& __d, const _Allocator& __a)
|
||||||
|
: _Base(__d, __a) { }
|
||||||
|
|
||||||
|
deque(deque&& __d, const _Allocator& __a)
|
||||||
|
: _Safe(std::move(__d)), _Base(std::move(__d), __a) { }
|
||||||
|
|
||||||
deque(initializer_list<value_type> __l,
|
deque(initializer_list<value_type> __l,
|
||||||
const allocator_type& __a = allocator_type())
|
const allocator_type& __a = allocator_type())
|
||||||
: _Base(__l, __a) { }
|
: _Base(__l, __a) { }
|
||||||
|
|
@ -101,8 +107,8 @@ namespace __debug
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
explicit
|
explicit
|
||||||
deque(size_type __n)
|
deque(size_type __n, const _Allocator& __a = _Allocator())
|
||||||
: _Base(__n) { }
|
: _Base(__n, __a) { }
|
||||||
|
|
||||||
deque(size_type __n, const _Tp& __value,
|
deque(size_type __n, const _Tp& __value,
|
||||||
const _Allocator& __a = _Allocator())
|
const _Allocator& __a = _Allocator())
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,12 @@ namespace __profile
|
||||||
deque(const deque&) = default;
|
deque(const deque&) = default;
|
||||||
deque(deque&&) = default;
|
deque(deque&&) = default;
|
||||||
|
|
||||||
|
deque(const deque& __d, const _Allocator& __a)
|
||||||
|
: _Base(__d, __a) { }
|
||||||
|
|
||||||
|
deque(deque&& __d, const _Allocator& __a)
|
||||||
|
: _Base(std::move(__d), __a) { }
|
||||||
|
|
||||||
~deque() = default;
|
~deque() = default;
|
||||||
|
|
||||||
deque(initializer_list<value_type> __l,
|
deque(initializer_list<value_type> __l,
|
||||||
|
|
@ -73,8 +79,8 @@ namespace __profile
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
explicit
|
explicit
|
||||||
deque(size_type __n)
|
deque(size_type __n, const _Allocator& __a = _Allocator())
|
||||||
: _Base(__n) { }
|
: _Base(__n, __a) { }
|
||||||
|
|
||||||
deque(size_type __n, const _Tp& __value,
|
deque(size_type __n, const _Tp& __value,
|
||||||
const _Allocator& __a = _Allocator())
|
const _Allocator& __a = _Allocator())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright (C) 2014 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++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, 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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(v1);
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(1 == v2.get_allocator().get_personality());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test03()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef propagating_allocator<T, true> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(v1, alloc_type(2));
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(2 == v2.get_allocator().get_personality());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (C) 2014 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++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(1, 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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(1, 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
struct T { int i; };
|
||||||
|
|
||||||
|
using __gnu_test::CustomPointerAlloc;
|
||||||
|
|
||||||
|
template class std::deque<T, CustomPointerAlloc<T>>;
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef CustomPointerAlloc<T> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v(1);
|
||||||
|
VERIFY( ++v.begin() == v.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
struct T { int i; };
|
||||||
|
|
||||||
|
using __gnu_test::SimpleAllocator;
|
||||||
|
|
||||||
|
template class std::deque<T, SimpleAllocator<T>>;
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef SimpleAllocator<T> alloc_type;
|
||||||
|
typedef std::allocator_traits<alloc_type> traits_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v(1, alloc_type{});
|
||||||
|
VERIFY( v.max_size() == traits_type::max_size(v.get_allocator()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
struct T { int i; };
|
||||||
|
|
||||||
|
using __gnu_test::uneq_allocator;
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef uneq_allocator<T> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
auto it = v1.begin();
|
||||||
|
test_type v2(std::move(v1));
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(1 == v2.get_allocator().get_personality());
|
||||||
|
VERIFY( it == v2.begin() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef uneq_allocator<T> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(std::move(v1), alloc_type(2));
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(2 == v2.get_allocator().get_personality());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (C) 2012-2014 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/>.
|
||||||
|
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++11 -fno-access-control" }
|
||||||
|
|
||||||
|
// libstdc++/52591
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
// As an extension we allow move-assignment of std::deque when the element
|
||||||
|
// type is not MoveAssignable, as long as the allocator type propagates or
|
||||||
|
// is known to always compare equal.
|
||||||
|
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C& operator=(C&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct A1 : std::allocator<T>
|
||||||
|
{
|
||||||
|
template<typename U> struct rebind { typedef A1<U> other; };
|
||||||
|
|
||||||
|
A1() = default;
|
||||||
|
template<typename U> A1(const A1<U>&) { }
|
||||||
|
|
||||||
|
using propagate_on_container_move_assignment = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
using test_type = std::deque<C, A1<C>>;
|
||||||
|
static_assert(std::is_move_assignable<test_type>::value,
|
||||||
|
"deque is move-assignable if allocator propagates");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct A2 : std::allocator<T>
|
||||||
|
{
|
||||||
|
template<typename U> struct rebind { typedef A2<U> other; };
|
||||||
|
|
||||||
|
A2() = default;
|
||||||
|
template<typename U> A2(const A2<U>&) { }
|
||||||
|
|
||||||
|
using propagate_on_container_move_assignment = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace __gnu_cxx
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct __allocator_always_compares_equal<A2<T>> : std::true_type
|
||||||
|
{ };
|
||||||
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
using test_type = std::deque<C, A2<C>>;
|
||||||
|
static_assert(std::is_nothrow_move_assignable<test_type>::value,
|
||||||
|
"deque is nothrow move-assignable if allocator is always equal");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (C) 2014 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++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(1, 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::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
auto it = v1.begin();
|
||||||
|
test_type v2(1, alloc_type(2));
|
||||||
|
v2 = std::move(v1);
|
||||||
|
VERIFY( it == v2.begin() );
|
||||||
|
VERIFY(0 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(1 == v2.get_allocator().get_personality());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test03()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef propagating_allocator<T, false> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
auto it = v1.begin();
|
||||||
|
test_type v2(1, alloc_type(1));
|
||||||
|
v2 = std::move(v1);
|
||||||
|
VERIFY( it == v2.begin() );
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(1 == v2.get_allocator().get_personality());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright (C) 2014 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/>.
|
||||||
|
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
struct T { int i; };
|
||||||
|
|
||||||
|
namespace __gnu_test
|
||||||
|
{
|
||||||
|
template<typename U>
|
||||||
|
inline void
|
||||||
|
swap(propagating_allocator<U, true>& l, propagating_allocator<U, true>& r)
|
||||||
|
noexcept(false)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
using __gnu_test::propagating_allocator;
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
typedef std::allocator<T> alloc_type;
|
||||||
|
typedef std::deque<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::deque<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::deque<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" );
|
||||||
|
// noexcept spec of deque::swap depends on swap overload at top of this file
|
||||||
|
static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (C) 2013 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++11" }
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
struct T { int i; };
|
||||||
|
|
||||||
|
using __gnu_test::propagating_allocator;
|
||||||
|
|
||||||
|
// It is undefined behaviour to swap() containers wth unequal allocators
|
||||||
|
// if the allocator doesn't propagate, so ensure the allocators compare
|
||||||
|
// equal, while still being able to test propagation via get_personality().
|
||||||
|
bool
|
||||||
|
operator==(const propagating_allocator<T, false>&,
|
||||||
|
const propagating_allocator<T, false>&)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!=(const propagating_allocator<T, false>&,
|
||||||
|
const propagating_allocator<T, false>&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef propagating_allocator<T, false> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(1, alloc_type(2));
|
||||||
|
std::swap(v1, v2);
|
||||||
|
VERIFY(1 == v1.get_allocator().get_personality());
|
||||||
|
VERIFY(2 == v2.get_allocator().get_personality());
|
||||||
|
// swap back so assertions in uneq_allocator::deallocate don't fail
|
||||||
|
std::swap(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
typedef propagating_allocator<T, true> alloc_type;
|
||||||
|
typedef std::deque<T, alloc_type> test_type;
|
||||||
|
test_type v1(1, alloc_type(1));
|
||||||
|
test_type v2(1, 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;
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
// { dg-error "no matching" "" { target *-*-* } 1764 }
|
// { dg-error "no matching" "" { target *-*-* } 1859 }
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
// { dg-error "no matching" "" { target *-*-* } 1697 }
|
// { dg-error "no matching" "" { target *-*-* } 1792 }
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
// { dg-error "no matching" "" { target *-*-* } 1697 }
|
// { dg-error "no matching" "" { target *-*-* } 1792 }
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
// { dg-error "no matching" "" { target *-*-* } 1848 }
|
// { dg-error "no matching" "" { target *-*-* } 1943 }
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
// libstdc++/52591
|
// libstdc++/52591
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
// As an extension we allow move-assignment of std::vector when the element
|
// As an extension we allow move-assignment of std::vector when the element
|
||||||
// type is not MoveAssignable, as long as the allocator type propagates or
|
// type is not MoveAssignable, as long as the allocator type propagates or
|
||||||
|
|
@ -31,8 +33,45 @@ struct C
|
||||||
C& operator=(C&&) = delete;
|
C& operator=(C&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct A1 : std::allocator<T>
|
||||||
|
{
|
||||||
|
template<typename U> struct rebind { typedef A1<U> other; };
|
||||||
|
|
||||||
|
A1() = default;
|
||||||
|
template<typename U> A1(const A1<U>&) { }
|
||||||
|
|
||||||
|
using propagate_on_container_move_assignment = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
void test01()
|
void test01()
|
||||||
{
|
{
|
||||||
std::vector<C> a;
|
using test_type = std::vector<C, A1<C>>;
|
||||||
a = std::vector<C>();
|
static_assert(std::is_nothrow_move_assignable<test_type>::value,
|
||||||
|
"vector is nothrow move-assignable if allocator propagates");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct A2 : std::allocator<T>
|
||||||
|
{
|
||||||
|
template<typename U> struct rebind { typedef A1<U> other; };
|
||||||
|
|
||||||
|
A2() = default;
|
||||||
|
template<typename U> A2(const A2<U>&) { }
|
||||||
|
|
||||||
|
using propagate_on_container_move_assignment = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace __gnu_cxx
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct __allocator_always_compares_equal<A2<T>> : std::true_type
|
||||||
|
{ };
|
||||||
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
using test_type = std::vector<C, A2<C>>;
|
||||||
|
static_assert(std::is_nothrow_move_assignable<test_type>::value,
|
||||||
|
"vector is nothrow move-assignable if allocator is always equal");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue