@@ -833,6 +833,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _ForwardIterator, typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
void
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
_Allocator& __alloc)
@@ -847,6 +848,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _ForwardIterator, typename _Tp>
+ _GLIBCXX20_CONSTEXPR
inline void
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
allocator<_Tp>&)
@@ -309,6 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
struct __shrink_to_fit_aux<_Tp, true>
{
+ _GLIBCXX20_CONSTEXPR
static bool
_S_do_it(_Tp& __c) noexcept
{
@@ -956,6 +956,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&,
const _VTp&);
+ _GLIBCXX20_CONSTEXPR
void
__fill_a1(_GLIBCXX_STD_C::_Bit_iterator, _GLIBCXX_STD_C::_Bit_iterator,
const bool&);
@@ -64,29 +64,38 @@
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef unsigned long _Bit_type;
enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) };
+ __attribute__((__nonnull__))
+ _GLIBCXX20_CONSTEXPR
+ void
+ __fill_bvector_n(_Bit_type*, size_t, bool) _GLIBCXX_NOEXCEPT;
+
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+
struct _Bit_reference
{
_Bit_type * _M_p;
_Bit_type _M_mask;
+ _GLIBCXX20_CONSTEXPR
_Bit_reference(_Bit_type * __x, _Bit_type __y)
: _M_p(__x), _M_mask(__y) { }
+ _GLIBCXX20_CONSTEXPR
_Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { }
#if __cplusplus >= 201103L
_Bit_reference(const _Bit_reference&) = default;
#endif
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
operator bool() const _GLIBCXX_NOEXCEPT
{ return !!(*_M_p & _M_mask); }
+ _GLIBCXX20_CONSTEXPR
_Bit_reference&
operator=(bool __x) _GLIBCXX_NOEXCEPT
{
@@ -97,26 +106,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
_Bit_reference&
operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT
{ return *this = bool(__x); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
bool
operator==(const _Bit_reference& __x) const
{ return bool(*this) == bool(__x); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
bool
operator<(const _Bit_reference& __x) const
{ return !bool(*this) && bool(__x); }
+ _GLIBCXX20_CONSTEXPR
void
flip() _GLIBCXX_NOEXCEPT
{ *_M_p ^= _M_mask; }
};
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
inline void
swap(_Bit_reference __x, _Bit_reference __y) noexcept
{
@@ -125,6 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__y = __tmp;
}
+ _GLIBCXX20_CONSTEXPR
inline void
swap(_Bit_reference __x, bool& __y) noexcept
{
@@ -133,6 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__y = __tmp;
}
+ _GLIBCXX20_CONSTEXPR
inline void
swap(bool& __x, _Bit_reference __y) noexcept
{
@@ -148,9 +162,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Bit_type * _M_p;
unsigned int _M_offset;
+ _GLIBCXX20_CONSTEXPR
_Bit_iterator_base(_Bit_type * __x, unsigned int __y)
: _M_p(__x), _M_offset(__y) { }
+ _GLIBCXX20_CONSTEXPR
void
_M_bump_up()
{
@@ -161,6 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
+ _GLIBCXX20_CONSTEXPR
void
_M_bump_down()
{
@@ -171,6 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
+ _GLIBCXX20_CONSTEXPR
void
_M_incr(ptrdiff_t __i)
{
@@ -230,7 +248,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return !(__x < __y); }
#endif // three-way comparison
- friend ptrdiff_t
+ friend _GLIBCXX20_CONSTEXPR ptrdiff_t
operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{
return (int(_S_word_bit) * (__x._M_p - __y._M_p)
@@ -248,20 +266,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
typedef _Bit_iterator iterator;
+ _GLIBCXX20_CONSTEXPR
_Bit_iterator() : _Bit_iterator_base(0, 0) { }
+ _GLIBCXX20_CONSTEXPR
_Bit_iterator(_Bit_type * __x, unsigned int __y)
: _Bit_iterator_base(__x, __y) { }
+ _GLIBCXX20_CONSTEXPR
iterator
_M_const_cast() const
{ return *this; }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator*() const
{ return reference(_M_p, 1UL << _M_offset); }
+ _GLIBCXX20_CONSTEXPR
iterator&
operator++()
{
@@ -269,6 +291,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
iterator
operator++(int)
{
@@ -277,6 +300,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __tmp;
}
+ _GLIBCXX20_CONSTEXPR
iterator&
operator--()
{
@@ -284,6 +308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
iterator
operator--(int)
{
@@ -292,6 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __tmp;
}
+ _GLIBCXX20_CONSTEXPR
iterator&
operator+=(difference_type __i)
{
@@ -299,6 +325,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
iterator&
operator-=(difference_type __i)
{
@@ -306,13 +333,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator[](difference_type __i) const
{ return *(*this + __i); }
_GLIBCXX_NODISCARD
- friend iterator
+ friend _GLIBCXX20_CONSTEXPR iterator
operator+(const iterator& __x, difference_type __n)
{
iterator __tmp = __x;
@@ -321,12 +348,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_GLIBCXX_NODISCARD
- friend iterator
+ friend _GLIBCXX20_CONSTEXPR iterator
operator+(difference_type __n, const iterator& __x)
{ return __x + __n; }
_GLIBCXX_NODISCARD
- friend iterator
+ friend _GLIBCXX20_CONSTEXPR iterator
operator-(const iterator& __x, difference_type __n)
{
iterator __tmp = __x;
@@ -346,23 +373,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
typedef _Bit_const_iterator const_iterator;
+ _GLIBCXX20_CONSTEXPR
_Bit_const_iterator() : _Bit_iterator_base(0, 0) { }
+ _GLIBCXX20_CONSTEXPR
_Bit_const_iterator(_Bit_type * __x, unsigned int __y)
: _Bit_iterator_base(__x, __y) { }
+ _GLIBCXX20_CONSTEXPR
_Bit_const_iterator(const _Bit_iterator& __x)
: _Bit_iterator_base(__x._M_p, __x._M_offset) { }
+ _GLIBCXX20_CONSTEXPR
_Bit_iterator
_M_const_cast() const
{ return _Bit_iterator(_M_p, _M_offset); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator*() const
{ return _Bit_reference(_M_p, 1UL << _M_offset); }
+ _GLIBCXX20_CONSTEXPR
const_iterator&
operator++()
{
@@ -370,6 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
const_iterator
operator++(int)
{
@@ -378,6 +411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __tmp;
}
+ _GLIBCXX20_CONSTEXPR
const_iterator&
operator--()
{
@@ -385,6 +419,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
const_iterator
operator--(int)
{
@@ -393,6 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __tmp;
}
+ _GLIBCXX20_CONSTEXPR
const_iterator&
operator+=(difference_type __i)
{
@@ -400,6 +436,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
const_iterator&
operator-=(difference_type __i)
{
@@ -407,13 +444,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator[](difference_type __i) const
{ return *(*this + __i); }
_GLIBCXX_NODISCARD
- friend const_iterator
+ friend _GLIBCXX20_CONSTEXPR const_iterator
operator+(const const_iterator& __x, difference_type __n)
{
const_iterator __tmp = __x;
@@ -422,7 +459,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_GLIBCXX_NODISCARD
- friend const_iterator
+ friend _GLIBCXX20_CONSTEXPR const_iterator
operator-(const const_iterator& __x, difference_type __n)
{
const_iterator __tmp = __x;
@@ -431,7 +468,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_GLIBCXX_NODISCARD
- friend const_iterator
+ friend _GLIBCXX20_CONSTEXPR const_iterator
operator+(difference_type __n, const const_iterator& __x)
{ return __x + __n; }
};
@@ -454,25 +491,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
struct {
_Bit_type* _M_p;
// Allow assignment from iterators (assume offset is zero):
+ _GLIBCXX20_CONSTEXPR
void operator=(_Bit_iterator __it) { _M_p = __it._M_p; }
} _M_start;
#endif
_Bit_iterator _M_finish;
_Bit_pointer _M_end_of_storage;
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl_data() _GLIBCXX_NOEXCEPT
: _M_start(), _M_finish(), _M_end_of_storage()
{ }
#if __cplusplus >= 201103L
_Bvector_impl_data(const _Bvector_impl_data&) = default;
+
_Bvector_impl_data&
operator=(const _Bvector_impl_data&) = default;
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl_data(_Bvector_impl_data&& __x) noexcept
: _Bvector_impl_data(__x)
{ __x._M_reset(); }
+ _GLIBCXX20_CONSTEXPR
void
_M_move_data(_Bvector_impl_data&& __x) noexcept
{
@@ -481,10 +523,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#endif
+ _GLIBCXX20_CONSTEXPR
void
_M_reset() _GLIBCXX_NOEXCEPT
{ *this = _Bvector_impl_data(); }
+ _GLIBCXX20_CONSTEXPR
void
_M_swap_data(_Bvector_impl_data& __x) _GLIBCXX_NOEXCEPT
{
@@ -497,11 +541,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
struct _Bvector_impl
: public _Bit_alloc_type, public _Bvector_impl_data
{
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl() _GLIBCXX_NOEXCEPT_IF(
is_nothrow_default_constructible<_Bit_alloc_type>::value)
: _Bit_alloc_type()
{ }
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT
: _Bit_alloc_type(__a)
{ }
@@ -509,15 +555,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
// Not defaulted, to enforce noexcept(true) even when
// !is_nothrow_move_constructible<_Bit_alloc_type>.
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl(_Bvector_impl&& __x) noexcept
: _Bit_alloc_type(std::move(__x)), _Bvector_impl_data(std::move(__x))
{ }
+ _GLIBCXX20_CONSTEXPR
_Bvector_impl(_Bit_alloc_type&& __a, _Bvector_impl&& __x) noexcept
: _Bit_alloc_type(std::move(__a)), _Bvector_impl_data(std::move(__x))
{ }
#endif
+ _GLIBCXX20_CONSTEXPR
_Bit_type*
_M_end_addr() const _GLIBCXX_NOEXCEPT
{
@@ -530,14 +579,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
public:
typedef _Alloc allocator_type;
+ _GLIBCXX20_CONSTEXPR
_Bit_alloc_type&
_M_get_Bit_allocator() _GLIBCXX_NOEXCEPT
{ return this->_M_impl; }
+ _GLIBCXX20_CONSTEXPR
const _Bit_alloc_type&
_M_get_Bit_allocator() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl; }
+ _GLIBCXX20_CONSTEXPR
allocator_type
get_allocator() const _GLIBCXX_NOEXCEPT
{ return allocator_type(_M_get_Bit_allocator()); }
@@ -548,27 +600,43 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Bvector_base() { }
#endif
+ _GLIBCXX20_CONSTEXPR
_Bvector_base(const allocator_type& __a)
: _M_impl(__a) { }
#if __cplusplus >= 201103L
_Bvector_base(_Bvector_base&&) = default;
+ _GLIBCXX20_CONSTEXPR
_Bvector_base(_Bvector_base&& __x, const allocator_type& __a) noexcept
: _M_impl(_Bit_alloc_type(__a), std::move(__x._M_impl))
{ }
#endif
+ _GLIBCXX20_CONSTEXPR
~_Bvector_base()
{ this->_M_deallocate(); }
protected:
_Bvector_impl _M_impl;
+ _GLIBCXX20_CONSTEXPR
_Bit_pointer
_M_allocate(size_t __n)
- { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); }
+ {
+ _Bit_pointer __p = _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n));
+#if __has_builtin(__builtin_is_constant_evaluated)
+ if (__builtin_is_constant_evaluated())
+ {
+ __n = _S_nword(__n);
+ for (size_t __i = 0; __i < __n; ++__i)
+ __p[__i] = 0ul;
+ }
+#endif
+ return __p;
+ }
+ _GLIBCXX20_CONSTEXPR
void
_M_deallocate()
{
@@ -583,11 +651,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
void
_M_move_data(_Bvector_base&& __x) noexcept
{ _M_impl._M_move_data(std::move(__x._M_impl)); }
#endif
+ _GLIBCXX_CONSTEXPR
static size_t
_S_nword(size_t __n)
{ return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); }
@@ -637,6 +707,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef _Alloc allocator_type;
+ _GLIBCXX20_CONSTEXPR
allocator_type
get_allocator() const
{ return _Base::get_allocator(); }
@@ -654,16 +725,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
vector() { }
#endif
+ _GLIBCXX20_CONSTEXPR
explicit
vector(const allocator_type& __a)
: _Base(__a) { }
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
explicit
vector(size_type __n, const allocator_type& __a = allocator_type())
: vector(__n, false, __a)
{ }
+ _GLIBCXX20_CONSTEXPR
vector(size_type __n, const bool& __value,
const allocator_type& __a = allocator_type())
#else
@@ -677,6 +751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_initialize_value(__value);
}
+ _GLIBCXX20_CONSTEXPR
vector(const vector& __x)
: _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator()))
{
@@ -688,10 +763,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
vector(vector&&) = default;
private:
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __x, const allocator_type& __a, true_type) noexcept
: _Base(std::move(__x), __a)
{ }
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __x, const allocator_type& __a, false_type)
: _Base(__a)
{
@@ -706,12 +783,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
public:
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
noexcept(_Bit_alloc_traits::_S_always_equal())
: vector(std::move(__x), __a,
typename _Bit_alloc_traits::is_always_equal{})
{ }
+ _GLIBCXX20_CONSTEXPR
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__a)
{
@@ -719,6 +798,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_copy_aligned(__x.begin(), __x.end(), begin());
}
+ _GLIBCXX20_CONSTEXPR
vector(initializer_list<bool> __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
@@ -731,6 +811,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type())
: _Base(__a)
@@ -750,8 +831,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#endif
+ _GLIBCXX20_CONSTEXPR
~vector() _GLIBCXX_NOEXCEPT { }
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(const vector& __x)
{
@@ -783,6 +866,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move())
{
@@ -808,6 +892,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(initializer_list<bool> __l)
{
@@ -820,6 +905,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// versions: one that takes a count, and one that takes a range.
// The range version is a member template, so we dispatch on whether
// or not the type is an integer.
+ _GLIBCXX20_CONSTEXPR
void
assign(size_type __n, const bool& __x)
{ _M_fill_assign(__n, __x); }
@@ -827,6 +913,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
void
assign(_InputIterator __first, _InputIterator __last)
{ _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
@@ -842,79 +929,80 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
void
assign(initializer_list<bool> __l)
{ _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); }
#endif
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
begin() _GLIBCXX_NOEXCEPT
{ return iterator(this->_M_impl._M_start._M_p, 0); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
begin() const _GLIBCXX_NOEXCEPT
{ return const_iterator(this->_M_impl._M_start._M_p, 0); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
end() _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_finish; }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
end() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_finish; }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(end()); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(end()); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(begin()); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(begin()); }
#if __cplusplus >= 201103L
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cbegin() const noexcept
{ return const_iterator(this->_M_impl._M_start._M_p, 0); }
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cend() const noexcept
{ return this->_M_impl._M_finish; }
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crbegin() const noexcept
{ return const_reverse_iterator(end()); }
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crend() const noexcept
{ return const_reverse_iterator(begin()); }
#endif
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
size() const _GLIBCXX_NOEXCEPT
{ return size_type(end() - begin()); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
max_size() const _GLIBCXX_NOEXCEPT
{
@@ -927,27 +1015,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
? __asize * int(_S_word_bit) : __isize);
}
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
capacity() const _GLIBCXX_NOEXCEPT
{ return size_type(const_iterator(this->_M_impl._M_end_addr(), 0)
- begin()); }
- _GLIBCXX_NODISCARD bool
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+ bool
empty() const _GLIBCXX_NOEXCEPT
{ return begin() == end(); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator[](size_type __n)
{ return begin()[__n]; }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator[](size_type __n) const
{ return begin()[__n]; }
protected:
+ _GLIBCXX20_CONSTEXPR
void
_M_range_check(size_type __n) const
{
@@ -959,14 +1049,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
public:
+ _GLIBCXX20_CONSTEXPR
reference
at(size_type __n)
- { _M_range_check(__n); return (*this)[__n]; }
+ {
+ _M_range_check(__n);
+ return (*this)[__n];
+ }
+ _GLIBCXX20_CONSTEXPR
const_reference
at(size_type __n) const
- { _M_range_check(__n); return (*this)[__n]; }
+ {
+ _M_range_check(__n);
+ return (*this)[__n];
+ }
+ _GLIBCXX20_CONSTEXPR
void
reserve(size_type __n)
{
@@ -976,26 +1075,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_reallocate(__n);
}
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
front()
{ return *begin(); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
front() const
{ return *begin(); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
back()
{ return *(end() - 1); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
back() const
{ return *(end() - 1); }
+ _GLIBCXX20_CONSTEXPR
void
push_back(bool __x)
{
@@ -1005,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_insert_aux(end(), __x);
}
+ _GLIBCXX20_CONSTEXPR
void
swap(vector& __x) _GLIBCXX_NOEXCEPT
{
@@ -1018,6 +1119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
// [23.2.5]/1, third-to-last entry in synopsis listing
+ _GLIBCXX20_CONSTEXPR
static void
swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT
{
@@ -1026,6 +1128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__y = __tmp;
}
+ _GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
insert(const_iterator __position, const bool& __x = bool())
@@ -1045,6 +1148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
@@ -1068,6 +1172,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, size_type __n, const bool& __x)
{
@@ -1082,15 +1187,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __p, initializer_list<bool> __l)
{ return this->insert(__p, __l.begin(), __l.end()); }
#endif
+ _GLIBCXX20_CONSTEXPR
void
pop_back()
{ --this->_M_impl._M_finish; }
+ _GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __position)
@@ -1099,6 +1207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
{ return _M_erase(__position._M_const_cast()); }
+ _GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __first, const_iterator __last)
@@ -1107,6 +1216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
{ return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
+ _GLIBCXX20_CONSTEXPR
void
resize(size_type __new_size, bool __x = bool())
{
@@ -1117,11 +1227,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
void
shrink_to_fit()
{ _M_shrink_to_fit(); }
#endif
+ _GLIBCXX20_CONSTEXPR
void
flip() _GLIBCXX_NOEXCEPT
{
@@ -1130,6 +1242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*__p = ~*__p;
}
+ _GLIBCXX20_CONSTEXPR
void
clear() _GLIBCXX_NOEXCEPT
{ _M_erase_at_end(begin()); }
@@ -1137,6 +1250,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename... _Args>
#if __cplusplus > 201402L
+ _GLIBCXX20_CONSTEXPR
reference
#else
void
@@ -1150,6 +1264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
iterator
emplace(const_iterator __pos, _Args&&... __args)
{ return insert(__pos, bool(__args...)); }
@@ -1157,6 +1272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
protected:
// Precondition: __first._M_offset == 0 && __result._M_offset == 0.
+ _GLIBCXX20_CONSTEXPR
iterator
_M_copy_aligned(const_iterator __first, const_iterator __last,
iterator __result)
@@ -1166,6 +1282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator(__q, 0));
}
+ _GLIBCXX20_CONSTEXPR
void
_M_initialize(size_type __n)
{
@@ -1179,19 +1296,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
+ _GLIBCXX20_CONSTEXPR
void
- _M_initialize_value(bool __x)
+ _M_initialize_value(bool __x) _GLIBCXX_NOEXCEPT
{
if (_Bit_type* __p = this->_M_impl._M_start._M_p)
- __builtin_memset(__p, __x ? ~0 : 0,
- (this->_M_impl._M_end_addr() - __p)
- * sizeof(_Bit_type));
+ __fill_bvector_n(__p, this->_M_impl._M_end_addr() - __p, __x);
}
+ _GLIBCXX20_CONSTEXPR
void
_M_reallocate(size_type __n);
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
bool
_M_shrink_to_fit();
#endif
@@ -1216,6 +1334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_initialize_range(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
@@ -1225,6 +1344,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_initialize_range(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag)
@@ -1249,6 +1369,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
#endif
+ _GLIBCXX20_CONSTEXPR
void
_M_fill_assign(size_t __n, bool __x)
{
@@ -1265,6 +1386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
@@ -1279,6 +1401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag)
@@ -1313,10 +1436,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::__iterator_category(__first)); }
#endif
+ _GLIBCXX20_CONSTEXPR
void
_M_fill_insert(iterator __position, size_type __n, bool __x);
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_range(iterator __pos, _InputIterator __first,
_InputIterator __last, std::input_iterator_tag)
@@ -1329,13 +1454,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_range(iterator __position, _ForwardIterator __first,
_ForwardIterator __last, std::forward_iterator_tag);
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_aux(iterator __position, bool __x);
+ _GLIBCXX20_CONSTEXPR
size_type
_M_check_len(size_type __n, const char* __s) const
{
@@ -1346,13 +1474,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return (__len < size() || __len > max_size()) ? max_size() : __len;
}
+ _GLIBCXX20_CONSTEXPR
void
_M_erase_at_end(iterator __pos)
{ this->_M_impl._M_finish = __pos; }
+ _GLIBCXX20_CONSTEXPR
iterator
_M_erase(iterator __pos);
+ _GLIBCXX20_CONSTEXPR
iterator
_M_erase(iterator __first, iterator __last);
@@ -1371,12 +1502,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX_END_NAMESPACE_CONTAINER
+ // Fill a partial word.
+ _GLIBCXX20_CONSTEXPR
inline void
- __fill_bvector(_GLIBCXX_STD_C::_Bit_type * __v,
- unsigned int __first, unsigned int __last, bool __x)
+ __fill_bvector(_Bit_type* __v, unsigned int __first, unsigned int __last,
+ bool __x) _GLIBCXX_NOEXCEPT
{
- using _GLIBCXX_STD_C::_Bit_type;
- using _GLIBCXX_STD_C::_S_word_bit;
const _Bit_type __fmask = ~0ul << __first;
const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last);
const _Bit_type __mask = __fmask & __lmask;
@@ -1387,20 +1518,36 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
*__v &= ~__mask;
}
+ // Fill N full words, as if using memset, but usable in constant expressions.
+ __attribute__((__nonnull__))
+ _GLIBCXX20_CONSTEXPR
+ inline void
+ __fill_bvector_n(_Bit_type* __p, size_t __n, bool __x) _GLIBCXX_NOEXCEPT
+ {
+#if __has_builtin(__builtin_is_constant_evaluated)
+ if (__builtin_is_constant_evaluated())
+ {
+ for (size_t __i = 0; __i < __n; ++__i)
+ __p[__i] = __x ? ~0ul : 0ul;
+ return;
+ }
+#endif
+ __builtin_memset(__p, __x ? ~0 : 0, __n * sizeof(_Bit_type));
+ }
+
+
+ _GLIBCXX20_CONSTEXPR
inline void
__fill_a1(_GLIBCXX_STD_C::_Bit_iterator __first,
_GLIBCXX_STD_C::_Bit_iterator __last, const bool& __x)
{
- using _GLIBCXX_STD_C::_Bit_type;
- using _GLIBCXX_STD_C::_S_word_bit;
if (__first._M_p != __last._M_p)
{
_Bit_type* __first_p = __first._M_p;
if (__first._M_offset != 0)
__fill_bvector(__first_p++, __first._M_offset, _S_word_bit, __x);
- __builtin_memset(__first_p, __x ? ~0 : 0,
- (__last._M_p - __first_p) * sizeof(_Bit_type));
+ __fill_bvector_n(__first_p, __last._M_p - __first_p, __x);
if (__last._M_offset != 0)
__fill_bvector(__last._M_p, 0, __last._M_offset, __x);
@@ -107,6 +107,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__is_trivial(T) && __is_assignable(T&, U)
#endif
+ template<typename _InputIterator, typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
+ _ForwardIterator
+ __do_uninit_copy(_InputIterator __first, _InputIterator __last,
+ _ForwardIterator __result)
+ {
+ _ForwardIterator __cur = __result;
+ __try
+ {
+ for (; __first != __last; ++__first, (void)++__cur)
+ std::_Construct(std::__addressof(*__cur), *__first);
+ return __cur;
+ }
+ __catch(...)
+ {
+ std::_Destroy(__result, __cur);
+ __throw_exception_again;
+ }
+ }
+
template<bool _TrivialValueTypes>
struct __uninitialized_copy
{
@@ -114,20 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static _ForwardIterator
__uninit_copy(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result)
- {
- _ForwardIterator __cur = __result;
- __try
- {
- for (; __first != __last; ++__first, (void)++__cur)
- std::_Construct(std::__addressof(*__cur), *__first);
- return __cur;
- }
- __catch(...)
- {
- std::_Destroy(__result, __cur);
- __throw_exception_again;
- }
- }
+ { return std::__do_uninit_copy(__first, __last, __result); }
};
template<>
@@ -180,6 +187,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
+ template<typename _ForwardIterator, typename _Tp>
+ _GLIBCXX20_CONSTEXPR void
+ __do_uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __x)
+ {
+ _ForwardIterator __cur = __first;
+ __try
+ {
+ for (; __cur != __last; ++__cur)
+ std::_Construct(std::__addressof(*__cur), __x);
+ }
+ __catch(...)
+ {
+ std::_Destroy(__first, __cur);
+ __throw_exception_again;
+ }
+ }
+
template<bool _TrivialValueType>
struct __uninitialized_fill
{
@@ -187,19 +212,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static void
__uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __x)
- {
- _ForwardIterator __cur = __first;
- __try
- {
- for (; __cur != __last; ++__cur)
- std::_Construct(std::__addressof(*__cur), __x);
- }
- __catch(...)
- {
- std::_Destroy(__first, __cur);
- __throw_exception_again;
- }
- }
+ { std::__do_uninit_fill(__first, __last, __x); }
};
template<>
@@ -242,34 +255,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
+ template<typename _ForwardIterator, typename _Size, typename _Tp>
+ _GLIBCXX20_CONSTEXPR
+ _ForwardIterator
+ __do_uninit_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
+ {
+ _ForwardIterator __cur = __first;
+ __try
+ {
+ for (; __n > 0; --__n, (void) ++__cur)
+ std::_Construct(std::__addressof(*__cur), __x);
+ return __cur;
+ }
+ __catch(...)
+ {
+ std::_Destroy(__first, __cur);
+ __throw_exception_again;
+ }
+ }
+
template<bool _TrivialValueType>
struct __uninitialized_fill_n
{
template<typename _ForwardIterator, typename _Size, typename _Tp>
- static _ForwardIterator
+ static _ForwardIterator
__uninit_fill_n(_ForwardIterator __first, _Size __n,
const _Tp& __x)
- {
- _ForwardIterator __cur = __first;
- __try
- {
- for (; __n > 0; --__n, (void) ++__cur)
- std::_Construct(std::__addressof(*__cur), __x);
- return __cur;
- }
- __catch(...)
- {
- std::_Destroy(__first, __cur);
- __throw_exception_again;
- }
- }
+ { return std::__do_uninit_fill_n(__first, __n, __x); }
};
template<>
struct __uninitialized_fill_n<true>
{
template<typename _ForwardIterator, typename _Size, typename _Tp>
- static _ForwardIterator
+ static _ForwardIterator
__uninit_fill_n(_ForwardIterator __first, _Size __n,
const _Tp& __x)
{ return std::fill_n(__first, __n, __x); }
@@ -315,11 +334,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Extensions: versions of uninitialized_copy, uninitialized_fill,
// and uninitialized_fill_n that take an allocator parameter.
// We dispatch back to the standard versions when we're given the
- // default allocator. For nondefault allocators we do not use
+ // default allocator. For nondefault allocators we do not use
// any of the POD optimizations.
template<typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
_ForwardIterator
__uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result, _Allocator& __alloc)
@@ -340,13 +360,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result, allocator<_Tp>&)
- { return std::uninitialized_copy(__first, __last, __result); }
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated())
+ return std::__do_uninit_copy(__first, __last, __result);
+#endif
+ return std::uninitialized_copy(__first, __last, __result);
+ }
template<typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__uninitialized_move_a(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result, _Allocator& __alloc)
@@ -358,6 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__uninitialized_move_if_noexcept_a(_InputIterator __first,
_InputIterator __last,
@@ -370,6 +399,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _ForwardIterator, typename _Tp, typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
void
__uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __x, _Allocator& __alloc)
@@ -389,15 +419,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _ForwardIterator, typename _Tp, typename _Tp2>
+ _GLIBCXX20_CONSTEXPR
inline void
__uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __x, allocator<_Tp2>&)
- { std::uninitialized_fill(__first, __last, __x); }
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated())
+ return std::__do_uninit_fill(__first, __last, __x);
+#endif
+ std::uninitialized_fill(__first, __last, __x);
+ }
template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
_ForwardIterator
- __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
+ __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, _Allocator& __alloc)
{
_ForwardIterator __cur = __first;
@@ -417,10 +455,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Tp2>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
- __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
+ __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, allocator<_Tp2>&)
- { return std::uninitialized_fill_n(__first, __n, __x); }
+ {
+#ifdef __cpp_lib_is_constant_evaluated
+ if (std::is_constant_evaluated())
+ return std::__do_uninit_fill_n(__first, __n, __x);
+#endif
+ return std::uninitialized_fill_n(__first, __n, __x);
+ }
// Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
@@ -483,7 +528,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_exception_again;
}
}
-
+
// __uninitialized_fill_move
// Fills [result, mid) with x, and moves [first, last) into
// [mid, mid + (last - first)).
@@ -582,6 +627,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __uninitialized_default_n_1
{
template<typename _ForwardIterator, typename _Size>
+ _GLIBCXX20_CONSTEXPR
static _ForwardIterator
__uninit_default_n(_ForwardIterator __first, _Size __n)
{
@@ -604,6 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __uninitialized_default_n_1<true>
{
template<typename _ForwardIterator, typename _Size>
+ _GLIBCXX20_CONSTEXPR
static _ForwardIterator
__uninit_default_n(_ForwardIterator __first, _Size __n)
{
@@ -639,6 +686,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __uninitialized_default_n
// Fills [first, first + n) with value-initialized value_types.
template<typename _ForwardIterator, typename _Size>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__uninitialized_default_n(_ForwardIterator __first, _Size __n)
{
@@ -689,8 +737,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Fills [first, first + n) with value_types constructed by the allocator
// alloc, with no arguments passed to the construct call.
template<typename _ForwardIterator, typename _Size, typename _Allocator>
- _ForwardIterator
- __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
+ _GLIBCXX20_CONSTEXPR _ForwardIterator
+ __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
_Allocator& __alloc)
{
_ForwardIterator __cur = __first;
@@ -711,8 +759,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __uninitialized_default_n_a specialization for std::allocator,
// which ignores the allocator and value-initializes the elements.
template<typename _ForwardIterator, typename _Size, typename _Tp>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
- __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
+ __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
allocator<_Tp>&)
{ return std::__uninitialized_default_n(__first, __n); }
@@ -1022,6 +1071,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: is_trivial<_Tp> { };
template <typename _Tp, typename _Up>
+ _GLIBCXX20_CONSTEXPR
inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
__relocate_a_1(_Tp* __first, _Tp* __last,
_Tp* __result, allocator<_Up>&) noexcept
@@ -1034,6 +1084,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__relocate_a_1(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result, _Allocator& __alloc)
@@ -1056,6 +1107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _InputIterator, typename _ForwardIterator,
typename _Allocator>
+ _GLIBCXX20_CONSTEXPR
inline _ForwardIterator
__relocate_a(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result, _Allocator& __alloc)
@@ -94,17 +94,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer _M_finish;
pointer _M_end_of_storage;
+ _GLIBCXX20_CONSTEXPR
_Vector_impl_data() _GLIBCXX_NOEXCEPT
: _M_start(), _M_finish(), _M_end_of_storage()
{ }
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
_Vector_impl_data(_Vector_impl_data&& __x) noexcept
: _M_start(__x._M_start), _M_finish(__x._M_finish),
_M_end_of_storage(__x._M_end_of_storage)
{ __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); }
#endif
+ _GLIBCXX20_CONSTEXPR
void
_M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPT
{
@@ -113,6 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_end_of_storage = __x._M_end_of_storage;
}
+ _GLIBCXX20_CONSTEXPR
void
_M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT
{
@@ -128,11 +132,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
struct _Vector_impl
: public _Tp_alloc_type, public _Vector_impl_data
{
+ _GLIBCXX20_CONSTEXPR
_Vector_impl() _GLIBCXX_NOEXCEPT_IF(
is_nothrow_default_constructible<_Tp_alloc_type>::value)
: _Tp_alloc_type()
{ }
+ _GLIBCXX20_CONSTEXPR
_Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(__a)
{ }
@@ -140,14 +146,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
// Not defaulted, to enforce noexcept(true) even when
// !is_nothrow_move_constructible<_Tp_alloc_type>.
+ _GLIBCXX20_CONSTEXPR
_Vector_impl(_Vector_impl&& __x) noexcept
: _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x))
{ }
+ _GLIBCXX20_CONSTEXPR
_Vector_impl(_Tp_alloc_type&& __a) noexcept
: _Tp_alloc_type(std::move(__a))
{ }
+ _GLIBCXX20_CONSTEXPR
_Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept
: _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv))
{ }
@@ -160,15 +169,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
::size_type size_type;
- static void _S_shrink(_Vector_impl&, size_type) { }
- static void _S_on_dealloc(_Vector_impl&) { }
+ static _GLIBCXX20_CONSTEXPR void
+ _S_shrink(_Vector_impl&, size_type) { }
+ static _GLIBCXX20_CONSTEXPR void
+ _S_on_dealloc(_Vector_impl&) { }
typedef _Vector_impl& _Reinit;
struct _Grow
{
- _Grow(_Vector_impl&, size_type) { }
- void _M_grew(size_type) { }
+ _GLIBCXX20_CONSTEXPR _Grow(_Vector_impl&, size_type) { }
+ _GLIBCXX20_CONSTEXPR void _M_grew(size_type) { }
};
};
@@ -181,22 +192,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Adjust ASan annotation for [_M_start, _M_end_of_storage) to
// mark end of valid region as __curr instead of __prev.
- static void
+ static _GLIBCXX20_CONSTEXPR void
_S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr)
{
+#if __has_builtin(__builtin_is_constant_evaluated)
+ if (!__builtin_is_constant_evaluated())
+#endif
__sanitizer_annotate_contiguous_container(__impl._M_start,
__impl._M_end_of_storage, __prev, __curr);
}
- static void
+ static _GLIBCXX20_CONSTEXPR void
_S_grow(_Vector_impl& __impl, size_type __n)
{ _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); }
- static void
+ static _GLIBCXX20_CONSTEXPR void
_S_shrink(_Vector_impl& __impl, size_type __n)
{ _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); }
- static void
+ static _GLIBCXX20_CONSTEXPR void
_S_on_dealloc(_Vector_impl& __impl)
{
if (__impl._M_start)
@@ -206,12 +220,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Used on reallocation to tell ASan unused capacity is invalid.
struct _Reinit
{
- explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
+ explicit _GLIBCXX20_CONSTEXPR
+ _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
{
// Mark unused capacity as valid again before deallocating it.
_S_on_dealloc(_M_impl);
}
+ _GLIBCXX20_CONSTEXPR
~_Reinit()
{
// Mark unused capacity as invalid after reallocation.
@@ -231,12 +247,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Tell ASan when unused capacity is initialized to be valid.
struct _Grow
{
+ _GLIBCXX20_CONSTEXPR
_Grow(_Vector_impl& __impl, size_type __n)
: _M_impl(__impl), _M_n(__n)
{ _S_grow(_M_impl, __n); }
+ _GLIBCXX20_CONSTEXPR
~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); }
+ _GLIBCXX20_CONSTEXPR
void _M_grew(size_type __n) { _M_n -= __n; }
#if __cplusplus >= 201103L
@@ -272,14 +291,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
public:
typedef _Alloc allocator_type;
+ _GLIBCXX20_CONSTEXPR
_Tp_alloc_type&
_M_get_Tp_allocator() _GLIBCXX_NOEXCEPT
{ return this->_M_impl; }
+ _GLIBCXX20_CONSTEXPR
const _Tp_alloc_type&
_M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl; }
+ _GLIBCXX20_CONSTEXPR
allocator_type
get_allocator() const _GLIBCXX_NOEXCEPT
{ return allocator_type(_M_get_Tp_allocator()); }
@@ -290,16 +312,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Vector_base() { }
#endif
+ _GLIBCXX20_CONSTEXPR
_Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT
: _M_impl(__a) { }
// Kept for ABI compatibility.
#if !_GLIBCXX_INLINE_VERSION
+ _GLIBCXX20_CONSTEXPR
_Vector_base(size_t __n)
: _M_impl()
{ _M_create_storage(__n); }
#endif
+ _GLIBCXX20_CONSTEXPR
_Vector_base(size_t __n, const allocator_type& __a)
: _M_impl(__a)
{ _M_create_storage(__n); }
@@ -309,9 +334,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Kept for ABI compatibility.
# if !_GLIBCXX_INLINE_VERSION
+ _GLIBCXX20_CONSTEXPR
_Vector_base(_Tp_alloc_type&& __a) noexcept
: _M_impl(std::move(__a)) { }
+ _GLIBCXX20_CONSTEXPR
_Vector_base(_Vector_base&& __x, const allocator_type& __a)
: _M_impl(__a)
{
@@ -325,11 +352,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
# endif
+ _GLIBCXX20_CONSTEXPR
_Vector_base(const allocator_type& __a, _Vector_base&& __x)
: _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl))
{ }
#endif
+ _GLIBCXX20_CONSTEXPR
~_Vector_base() _GLIBCXX_NOEXCEPT
{
_M_deallocate(_M_impl._M_start,
@@ -339,6 +368,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
public:
_Vector_impl _M_impl;
+ _GLIBCXX20_CONSTEXPR
pointer
_M_allocate(size_t __n)
{
@@ -346,6 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer();
}
+ _GLIBCXX20_CONSTEXPR
void
_M_deallocate(pointer __p, size_t __n)
{
@@ -355,6 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
protected:
+ _GLIBCXX20_CONSTEXPR
void
_M_create_storage(size_t __n)
{
@@ -443,25 +475,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
static constexpr bool
_S_use_relocate()
{
+#if __cplusplus >= 202002L && __has_builtin(__builtin_is_constant_evaluated)
+ if (__builtin_is_constant_evaluated())
+ return false; // Cannot use memcpy in constant evaluation contexts.
+#endif
// Instantiating std::__relocate_a might cause an error outside the
// immediate context (in __relocate_object_a's noexcept-specifier),
// so only do it if we know the type can be move-inserted into *this.
return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{});
}
- static pointer
+ static _GLIBCXX20_CONSTEXPR pointer
_S_do_relocate(pointer __first, pointer __last, pointer __result,
_Tp_alloc_type& __alloc, true_type) noexcept
{
return std::__relocate_a(__first, __last, __result, __alloc);
}
- static pointer
+ static _GLIBCXX20_CONSTEXPR pointer
_S_do_relocate(pointer, pointer, pointer __result,
_Tp_alloc_type&, false_type) noexcept
{ return __result; }
- static pointer
+ static _GLIBCXX20_CONSTEXPR pointer
_S_relocate(pointer __first, pointer __last, pointer __result,
_Tp_alloc_type& __alloc) noexcept
{
@@ -494,6 +530,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @param __a An allocator object.
*/
explicit
+ _GLIBCXX20_CONSTEXPR
vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
: _Base(__a) { }
@@ -507,6 +544,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* constructed elements.
*/
explicit
+ _GLIBCXX20_CONSTEXPR
vector(size_type __n, const allocator_type& __a = allocator_type())
: _Base(_S_check_init_len(__n, __a), __a)
{ _M_default_initialize(__n); }
@@ -519,6 +557,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* This constructor fills the %vector with @a __n copies of @a __value.
*/
+ _GLIBCXX20_CONSTEXPR
vector(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type())
: _Base(_S_check_init_len(__n, __a), __a)
@@ -550,6 +589,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* The newly-created %vector uses a copy of the allocator object used
* by @a __x (unless the allocator traits dictate a different object).
*/
+ _GLIBCXX20_CONSTEXPR
vector(const vector& __x)
: _Base(__x.size(),
_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
@@ -572,6 +612,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
vector(vector&&) noexcept = default;
/// Copy constructor with alternative allocator
+ _GLIBCXX20_CONSTEXPR
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
: _Base(__x.size(), __a)
{
@@ -582,10 +623,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
private:
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __rv, const allocator_type& __m, true_type) noexcept
: _Base(__m, std::move(__rv))
{ }
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __rv, const allocator_type& __m, false_type)
: _Base(__m)
{
@@ -604,6 +647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
public:
/// Move constructor with alternative allocator
+ _GLIBCXX20_CONSTEXPR
vector(vector&& __rv, const __type_identity_t<allocator_type>& __m)
noexcept( noexcept(
vector(std::declval<vector&&>(), std::declval<const allocator_type&>(),
@@ -622,6 +666,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* This will call the element type's copy constructor N times
* (where N is @a __l.size()) and do no memory reallocation.
*/
+ _GLIBCXX20_CONSTEXPR
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
@@ -650,6 +695,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type())
: _Base(__a)
@@ -675,6 +721,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* not touched in any way. Managing the pointer is the user's
* responsibility.
*/
+ _GLIBCXX20_CONSTEXPR
~vector() _GLIBCXX_NOEXCEPT
{
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
@@ -691,6 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* Whether the allocator is copied depends on the allocator traits.
*/
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(const vector& __x);
@@ -705,6 +753,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* Whether the allocator is moved depends on the allocator traits.
*/
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
{
@@ -726,6 +775,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* that the resulting %vector's size is the same as the number
* of elements assigned.
*/
+ _GLIBCXX20_CONSTEXPR
vector&
operator=(initializer_list<value_type> __l)
{
@@ -745,6 +795,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %vector and that the resulting %vector's size is the same as
* the number of elements assigned.
*/
+ _GLIBCXX20_CONSTEXPR
void
assign(size_type __n, const value_type& __val)
{ _M_fill_assign(__n, __val); }
@@ -764,6 +815,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
void
assign(_InputIterator __first, _InputIterator __last)
{ _M_assign_dispatch(__first, __last, __false_type()); }
@@ -790,6 +842,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* that the resulting %vector's size is the same as the number
* of elements assigned.
*/
+ _GLIBCXX20_CONSTEXPR
void
assign(initializer_list<value_type> __l)
{
@@ -807,7 +860,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* element in the %vector. Iteration is done in ordinary
* element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
begin() _GLIBCXX_NOEXCEPT
{ return iterator(this->_M_impl._M_start); }
@@ -817,7 +870,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* first element in the %vector. Iteration is done in ordinary
* element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
begin() const _GLIBCXX_NOEXCEPT
{ return const_iterator(this->_M_impl._M_start); }
@@ -827,7 +880,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* element in the %vector. Iteration is done in ordinary
* element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
end() _GLIBCXX_NOEXCEPT
{ return iterator(this->_M_impl._M_finish); }
@@ -837,7 +890,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* the last element in the %vector. Iteration is done in
* ordinary element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
end() const _GLIBCXX_NOEXCEPT
{ return const_iterator(this->_M_impl._M_finish); }
@@ -847,7 +900,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* last element in the %vector. Iteration is done in reverse
* element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(end()); }
@@ -857,7 +910,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* to the last element in the %vector. Iteration is done in
* reverse element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(end()); }
@@ -867,7 +920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* before the first element in the %vector. Iteration is done
* in reverse element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(begin()); }
@@ -877,7 +930,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* to one before the first element in the %vector. Iteration
* is done in reverse element order.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(begin()); }
@@ -888,7 +941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* first element in the %vector. Iteration is done in ordinary
* element order.
*/
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cbegin() const noexcept
{ return const_iterator(this->_M_impl._M_start); }
@@ -898,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* the last element in the %vector. Iteration is done in
* ordinary element order.
*/
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cend() const noexcept
{ return const_iterator(this->_M_impl._M_finish); }
@@ -908,7 +961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* to the last element in the %vector. Iteration is done in
* reverse element order.
*/
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crbegin() const noexcept
{ return const_reverse_iterator(end()); }
@@ -918,7 +971,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* to one before the first element in the %vector. Iteration
* is done in reverse element order.
*/
- [[__nodiscard__]]
+ [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crend() const noexcept
{ return const_reverse_iterator(begin()); }
@@ -926,13 +979,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
size() const _GLIBCXX_NOEXCEPT
{ return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
/** Returns the size() of the largest possible %vector. */
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
max_size() const _GLIBCXX_NOEXCEPT
{ return _S_max_size(_M_get_Tp_allocator()); }
@@ -947,6 +1000,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %vector's current size the %vector is truncated, otherwise
* default constructed elements are appended.
*/
+ _GLIBCXX20_CONSTEXPR
void
resize(size_type __new_size)
{
@@ -967,6 +1021,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* the %vector is extended and new elements are populated with
* given data.
*/
+ _GLIBCXX20_CONSTEXPR
void
resize(size_type __new_size, const value_type& __x)
{
@@ -987,6 +1042,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* the %vector is extended and new elements are populated with
* given data.
*/
+ _GLIBCXX20_CONSTEXPR
void
resize(size_type __new_size, value_type __x = value_type())
{
@@ -999,6 +1055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
/** A non-binding request to reduce capacity() to size(). */
+ _GLIBCXX20_CONSTEXPR
void
shrink_to_fit()
{ _M_shrink_to_fit(); }
@@ -1008,7 +1065,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns the total number of elements that the %vector can
* hold before needing to allocate more memory.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
capacity() const _GLIBCXX_NOEXCEPT
{ return size_type(this->_M_impl._M_end_of_storage
@@ -1018,7 +1075,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns true if the %vector is empty. (Thus begin() would
* equal end().)
*/
- _GLIBCXX_NODISCARD bool
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+ bool
empty() const _GLIBCXX_NOEXCEPT
{ return begin() == end(); }
@@ -1039,6 +1097,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %advance, and thus prevent a possible reallocation of memory
* and copying of %vector data.
*/
+ _GLIBCXX20_CONSTEXPR
void
reserve(size_type __n);
@@ -1054,7 +1113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* out_of_range lookups are not defined. (For checked lookups
* see at().)
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
@@ -1073,7 +1132,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* out_of_range lookups are not defined. (For checked lookups
* see at().)
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator[](size_type __n) const _GLIBCXX_NOEXCEPT
{
@@ -1083,6 +1142,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
protected:
/// Safety check used only from at().
+ _GLIBCXX20_CONSTEXPR
void
_M_range_check(size_type __n) const
{
@@ -1105,6 +1165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* is first checked that it is in the range of the vector. The
* function throws out_of_range if the check fails.
*/
+ _GLIBCXX20_CONSTEXPR
reference
at(size_type __n)
{
@@ -1123,6 +1184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* is first checked that it is in the range of the vector. The
* function throws out_of_range if the check fails.
*/
+ _GLIBCXX20_CONSTEXPR
const_reference
at(size_type __n) const
{
@@ -1134,7 +1196,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns a read/write reference to the data at the first
* element of the %vector.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
front() _GLIBCXX_NOEXCEPT
{
@@ -1146,7 +1208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns a read-only (constant) reference to the data at the first
* element of the %vector.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
front() const _GLIBCXX_NOEXCEPT
{
@@ -1158,7 +1220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns a read/write reference to the data at the last
* element of the %vector.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
back() _GLIBCXX_NOEXCEPT
{
@@ -1170,7 +1232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns a read-only (constant) reference to the data at the
* last element of the %vector.
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
back() const _GLIBCXX_NOEXCEPT
{
@@ -1185,12 +1247,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* Returns a pointer such that [data(), data() + size()) is a valid
* range. For a non-empty %vector, data() == &front().
*/
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
_Tp*
data() _GLIBCXX_NOEXCEPT
{ return _M_data_ptr(this->_M_impl._M_start); }
- _GLIBCXX_NODISCARD
+ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const _Tp*
data() const _GLIBCXX_NOEXCEPT
{ return _M_data_ptr(this->_M_impl._M_start); }
@@ -1206,6 +1268,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* done in constant time if the %vector has preallocated space
* available.
*/
+ _GLIBCXX20_CONSTEXPR
void
push_back(const value_type& __x)
{
@@ -1222,12 +1285,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#if __cplusplus >= 201103L
+ _GLIBCXX20_CONSTEXPR
void
push_back(value_type&& __x)
{ emplace_back(std::move(__x)); }
template<typename... _Args>
#if __cplusplus > 201402L
+ _GLIBCXX20_CONSTEXPR
reference
#else
void
@@ -1244,6 +1309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* data is needed, it should be retrieved before pop_back() is
* called.
*/
+ _GLIBCXX20_CONSTEXPR
void
pop_back() _GLIBCXX_NOEXCEPT
{
@@ -1267,6 +1333,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* std::list.
*/
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
iterator
emplace(const_iterator __position, _Args&&... __args)
{ return _M_emplace_aux(__position, std::forward<_Args>(__args)...); }
@@ -1282,6 +1349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* could be expensive for a %vector and if it is frequently
* used the user should consider using std::list.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, const value_type& __x);
#else
@@ -1312,6 +1380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* could be expensive for a %vector and if it is frequently
* used the user should consider using std::list.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, value_type&& __x)
{ return _M_insert_rval(__position, std::move(__x)); }
@@ -1329,6 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %vector and if it is frequently used the user should
* consider using std::list.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, initializer_list<value_type> __l)
{
@@ -1354,6 +1424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %vector and if it is frequently used the user should
* consider using std::list.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, size_type __n, const value_type& __x)
{
@@ -1398,6 +1469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*/
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
+ _GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, _InputIterator __first,
_InputIterator __last)
@@ -1448,6 +1520,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* the pointed-to memory is not touched in any way. Managing
* the pointer is the user's responsibility.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __position)
@@ -1475,6 +1548,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* pointers, the pointed-to memory is not touched in any way.
* Managing the pointer is the user's responsibility.
*/
+ _GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __first, const_iterator __last)
@@ -1499,6 +1573,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* Whether the allocators are swapped depends on the allocator traits.
*/
+ _GLIBCXX20_CONSTEXPR
void
swap(vector& __x) _GLIBCXX_NOEXCEPT
{
@@ -1517,6 +1592,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* pointed-to memory is not touched in any way. Managing the pointer is
* the user's responsibility.
*/
+ _GLIBCXX20_CONSTEXPR
void
clear() _GLIBCXX_NOEXCEPT
{ _M_erase_at_end(this->_M_impl._M_start); }
@@ -1527,6 +1603,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* obtain @a n bytes of memory, and then copies [first,last) into it.
*/
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
pointer
_M_allocate_and_copy(size_type __n,
_ForwardIterator __first, _ForwardIterator __last)
@@ -1577,6 +1654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the second initialize_dispatch above
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_range_initialize(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
@@ -1596,6 +1674,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the second initialize_dispatch above
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag)
@@ -1612,6 +1691,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the first initialize_dispatch above and by the
// vector(n,value,a) constructor.
+ _GLIBCXX20_CONSTEXPR
void
_M_fill_initialize(size_type __n, const value_type& __value)
{
@@ -1622,6 +1702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
// Called by the vector(n) constructor.
+ _GLIBCXX20_CONSTEXPR
void
_M_default_initialize(size_type __n)
{
@@ -1639,12 +1720,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
{ _M_fill_assign(__n, __val); }
// Called by the range assign to implement [23.1.1]/9
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_dispatch(_InputIterator __first, _InputIterator __last,
__false_type)
@@ -1652,18 +1735,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the second assign_dispatch above
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag);
// Called by the second assign_dispatch above
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag);
// Called by assign(n,t), and the range assign when it turns out
// to be the same thing.
+ _GLIBCXX20_CONSTEXPR
void
_M_fill_assign(size_type __n, const value_type& __val);
@@ -1674,6 +1760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
__true_type)
@@ -1681,6 +1768,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the range insert to implement [23.1.1]/9
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_dispatch(iterator __pos, _InputIterator __first,
_InputIterator __last, __false_type)
@@ -1691,26 +1779,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by the second insert_dispatch above
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_range_insert(iterator __pos, _InputIterator __first,
_InputIterator __last, std::input_iterator_tag);
// Called by the second insert_dispatch above
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
_M_range_insert(iterator __pos, _ForwardIterator __first,
_ForwardIterator __last, std::forward_iterator_tag);
// Called by insert(p,n,x), and the range insert when it turns out to be
// the same thing.
+ _GLIBCXX20_CONSTEXPR
void
_M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
#if __cplusplus >= 201103L
// Called by resize(n).
+ _GLIBCXX20_CONSTEXPR
void
_M_default_append(size_type __n);
+ _GLIBCXX20_CONSTEXPR
bool
_M_shrink_to_fit();
#endif
@@ -1728,53 +1821,69 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
struct _Temporary_value
{
template<typename... _Args>
- explicit
+ _GLIBCXX20_CONSTEXPR explicit
_Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec)
{
_Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
std::forward<_Args>(__args)...);
}
+ _GLIBCXX20_CONSTEXPR
~_Temporary_value()
{ _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
- value_type&
- _M_val() { return *_M_ptr(); }
+ _GLIBCXX20_CONSTEXPR value_type&
+ _M_val() noexcept { return _M_storage._M_val; }
private:
- _Tp*
- _M_ptr() { return reinterpret_cast<_Tp*>(&__buf); }
+ _GLIBCXX20_CONSTEXPR _Tp*
+ _M_ptr() noexcept { return std::__addressof(_M_storage._M_val); }
- vector* _M_this;
- typename aligned_storage<sizeof(_Tp), alignof(_Tp)>::type __buf;
+ union _Storage
+ {
+ constexpr _Storage() : _M_byte() { }
+ _GLIBCXX20_CONSTEXPR ~_Storage() { }
+ _Storage& operator=(const _Storage&) = delete;
+ unsigned char _M_byte;
+ _Tp _M_val;
+ };
+
+ vector* _M_this;
+ _Storage _M_storage;
};
// Called by insert(p,x) and other functions when insertion needs to
// reallocate or move existing elements. _Arg is either _Tp& or _Tp.
template<typename _Arg>
+ _GLIBCXX20_CONSTEXPR
void
_M_insert_aux(iterator __position, _Arg&& __arg);
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
void
_M_realloc_insert(iterator __position, _Args&&... __args);
// Either move-construct at the end, or forward to _M_insert_aux.
+ _GLIBCXX20_CONSTEXPR
iterator
_M_insert_rval(const_iterator __position, value_type&& __v);
// Try to emplace at the end, otherwise forward to _M_insert_aux.
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
iterator
_M_emplace_aux(const_iterator __position, _Args&&... __args);
// Emplacing an rvalue of the correct type can use _M_insert_rval.
+ _GLIBCXX20_CONSTEXPR
iterator
_M_emplace_aux(const_iterator __position, value_type&& __v)
{ return _M_insert_rval(__position, std::move(__v)); }
#endif
// Called by _M_fill_insert, _M_insert_aux etc.
+ _GLIBCXX20_CONSTEXPR
size_type
_M_check_len(size_type __n, const char* __s) const
{
@@ -1786,7 +1895,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
// Called by constructors to check initial size.
- static size_type
+ static _GLIBCXX20_CONSTEXPR size_type
_S_check_init_len(size_type __n, const allocator_type& __a)
{
if (__n > _S_max_size(_Tp_alloc_type(__a)))
@@ -1795,7 +1904,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __n;
}
- static size_type
+ static _GLIBCXX20_CONSTEXPR size_type
_S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
{
// std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX,
@@ -1811,6 +1920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
// _M_assign_aux.
+ _GLIBCXX20_CONSTEXPR
void
_M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT
{
@@ -1823,9 +1933,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
}
+ _GLIBCXX20_CONSTEXPR
iterator
_M_erase(iterator __position);
+ _GLIBCXX20_CONSTEXPR
iterator
_M_erase(iterator __first, iterator __last);
@@ -1834,6 +1946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Constant-time move assignment when source object's memory can be
// moved, either because the source's allocator will move too
// or because the allocators are equal.
+ _GLIBCXX20_CONSTEXPR
void
_M_move_assign(vector&& __x, true_type) noexcept
{
@@ -1845,6 +1958,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Do move assignment when it might not be possible to move source
// object's memory, resulting in a linear-time operation.
+ _GLIBCXX20_CONSTEXPR
void
_M_move_assign(vector&& __x, false_type)
{
@@ -1863,12 +1977,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
template<typename _Up>
+ _GLIBCXX20_CONSTEXPR
_Up*
_M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT
{ return __ptr; }
#if __cplusplus >= 201103L
template<typename _Ptr>
+ _GLIBCXX20_CONSTEXPR
typename std::pointer_traits<_Ptr>::element_type*
_M_data_ptr(_Ptr __ptr) const
{ return empty() ? nullptr : std::__to_address(__ptr); }
@@ -1911,6 +2027,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* and if corresponding elements compare equal.
*/
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
inline bool
operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
{ return (__x.size() == __y.size()
@@ -1929,6 +2046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* `<` and `>=` etc.
*/
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
inline __detail::__synth3way_t<_Tp>
operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
{
@@ -1981,6 +2099,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/// See std::vector::swap().
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
inline void
swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
_GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
@@ -62,6 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
reserve(size_type __n)
@@ -102,6 +103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename... _Args>
#if __cplusplus > 201402L
+ _GLIBCXX20_CONSTEXPR
typename vector<_Tp, _Alloc>::reference
#else
void
@@ -126,6 +128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
#if __cplusplus >= 201103L
@@ -167,6 +170,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
_M_erase(iterator __position)
@@ -180,6 +184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
_M_erase(iterator __first, iterator __last)
@@ -194,6 +199,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
vector<_Tp, _Alloc>&
vector<_Tp, _Alloc>::
operator=(const vector<_Tp, _Alloc>& __x)
@@ -253,6 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_fill_assign(size_t __n, const value_type& __val)
@@ -278,6 +285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_assign_aux(_InputIterator __first, _InputIterator __last,
@@ -296,6 +304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
@@ -336,6 +345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
auto
vector<_Tp, _Alloc>::
_M_insert_rval(const_iterator __position, value_type&& __v) -> iterator
@@ -360,6 +370,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
auto
vector<_Tp, _Alloc>::
_M_emplace_aux(const_iterator __position, _Args&&... __args)
@@ -391,6 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename _Arg>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_insert_aux(iterator __position, _Arg&& __arg)
@@ -422,6 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
template<typename... _Args>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_realloc_insert(iterator __position, _Args&&... __args)
@@ -505,6 +518,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_fill_insert(iterator __position, size_type __n, const value_type& __x)
@@ -607,6 +621,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_default_append(size_type __n)
@@ -683,6 +698,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Tp, typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
bool
vector<_Tp, _Alloc>::
_M_shrink_to_fit()
@@ -696,6 +712,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename _InputIterator>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_range_insert(iterator __pos, _InputIterator __first,
@@ -717,6 +734,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
vector<_Tp, _Alloc>::
_M_range_insert(iterator __position, _ForwardIterator __first,
@@ -806,6 +824,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// vector<bool>
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<bool, _Alloc>::
_M_reallocate(size_type __n)
@@ -820,6 +839,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<bool, _Alloc>::
_M_fill_insert(iterator __position, size_type __n, bool __x)
@@ -852,6 +872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Alloc>
template<typename _ForwardIterator>
+ _GLIBCXX20_CONSTEXPR
void
vector<bool, _Alloc>::
_M_insert_range(iterator __position, _ForwardIterator __first,
@@ -886,6 +907,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
void
vector<bool, _Alloc>::
_M_insert_aux(iterator __position, bool __x)
@@ -914,6 +936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
typename vector<bool, _Alloc>::iterator
vector<bool, _Alloc>::
_M_erase(iterator __position)
@@ -925,6 +948,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
typename vector<bool, _Alloc>::iterator
vector<bool, _Alloc>::
_M_erase(iterator __first, iterator __last)
@@ -936,6 +960,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<typename _Alloc>
+ _GLIBCXX20_CONSTEXPR
bool
vector<bool, _Alloc>::
_M_shrink_to_fit()
@@ -974,9 +999,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept
{
size_t __hash = 0;
- using _GLIBCXX_STD_C::_S_word_bit;
- using _GLIBCXX_STD_C::_Bit_type;
-
const size_t __words = __b.size() / _S_word_bit;
if (__words)
{
@@ -102,6 +102,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __cpp_lib_erase_if 202002L
template<typename _Tp, typename _Alloc, typename _Predicate>
+ _GLIBCXX20_CONSTEXPR
inline typename vector<_Tp, _Alloc>::size_type
erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
@@ -115,6 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _Tp, typename _Alloc, typename _Up>
+ _GLIBCXX20_CONSTEXPR
inline typename vector<_Tp, _Alloc>::size_type
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
{
@@ -27,13 +27,21 @@
# define NOTHROW(X)
#endif
+#if __cplusplus >= 202002L
+# define CONSTEXPR constexpr
+#else
+# define CONSTEXPR
+#endif
+
namespace std {
template <class T, class Allocator> class vector;
template <class T, class Allocator>
+ CONSTEXPR
bool operator==(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
+#if __cplusplus < 202002L
template <class T, class Allocator>
bool operator< (const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
@@ -53,17 +61,21 @@ namespace std {
template <class T, class Allocator>
bool operator<=(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
+#endif
template <class T, class Allocator>
+ CONSTEXPR
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
NOTHROW(noexcept(x.swap(y)));
template <class Allocator> class vector<bool,Allocator>;
template <class Allocator>
+ CONSTEXPR
bool operator==(const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
+#if __cplusplus < 202002L
template <class Allocator>
bool operator< (const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
@@ -83,7 +95,9 @@ namespace std {
template <class Allocator>
bool operator<=(const vector<bool,Allocator>& x,
const vector<bool,Allocator>& y);
+#endif
template <class Allocator>
+ CONSTEXPR
void swap(vector<bool,Allocator>& x, vector<bool,Allocator>& y);
}
@@ -26,12 +26,7 @@ void test01()
{
using std::vector;
using std::numeric_limits;
-
-#ifdef _GLIBCXX_DEBUG
- using std::_GLIBCXX_STD_C::_S_word_bit;
-#else
using std::_S_word_bit;
-#endif
// Actually, vector<bool> is special, see libstdc++/31370.
vector<bool> vb;
new file mode 100644
@@ -0,0 +1,115 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+test_empty()
+{
+ std::vector<bool> v;
+ VERIFY( v.empty() );
+ v = {1};
+ VERIFY( !v.empty() );
+
+ return true;
+}
+
+static_assert( test_empty() );
+
+constexpr bool
+test_size()
+{
+ std::vector<bool> v;
+ VERIFY( v.size() == 0 );
+ v = {1};
+ VERIFY( v.size() == 1 );
+
+ VERIFY( v.max_size() != 0 );
+
+ return true;
+}
+
+static_assert( test_size() );
+
+constexpr bool
+test_capacity()
+{
+ std::vector<bool> v;
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == v.size() );
+ v = {false, false, false};
+ VERIFY( v.size() == 3 );
+ VERIFY( v.capacity() >= v.size() );
+
+ return true;
+}
+
+static_assert( test_capacity() );
+
+constexpr bool
+test_resize()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(5);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(900, true);
+ VERIFY( v.size() == 900 );
+ VERIFY( v.capacity() == capacity_for(900) );
+ VERIFY( v[10] == true );
+
+ return true;
+}
+
+static_assert( test_resize() );
+
+constexpr bool
+test_reserve()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(2);
+ VERIFY( v.size() == 2 );
+ VERIFY( v.capacity() == capacity_for(9) );
+ v.resize(300);
+ v.resize(100);
+ VERIFY( v.size() == 100 );
+ VERIFY( v.capacity() == capacity_for(300) );
+
+ return true;
+}
+
+static_assert( test_reserve() );
+
+constexpr bool
+test_shrink_to_fit()
+{
+ std::vector<bool> v;
+ v.reserve(9);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == 0 );
+ v.reserve(9);
+ v.resize(5);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == capacity_for(v.size()) );
+
+ return true;
+}
+
+static_assert( test_shrink_to_fit() );
@@ -16,12 +16,13 @@
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
-// { dg-do run { target c++2a } }
+// { dg-do compile { target c++2a } }
+// { dg-xfail-if "not supported" { debug-mode } }
#include <vector>
#include <testsuite_hooks.h>
-void
+constexpr bool
test01()
{
std::vector<bool> c1{ 1, 0, 1 }, c2{ 1, 0, 1, 0 }, c3{ 1, 1, 1 };
@@ -38,9 +39,11 @@ test01()
static_assert( std::three_way_comparable<std::vector<bool>,
std::strong_ordering> );
+
+ return true;
}
-void
+constexpr bool
test05()
{
// vector<bool> iterators are random access, so should support <=>
@@ -63,11 +66,9 @@ test05()
static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
std::strong_ordering> );
+
+ return true;
}
-int
-main()
-{
- test01();
- test05();
-}
+static_assert( test01() );
+static_assert( test05() );
new file mode 100644
@@ -0,0 +1,280 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr Alloc select_on_container_copy_construction() const
+ { return Alloc(-1); }
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+namespace default_constructor_global_scope
+{
+ constexpr std::vector<bool> v1;
+ static_assert(v1.size() == 0);
+ static_assert(v1.capacity() == 0);
+
+ constexpr std::allocator<bool> a;
+ constexpr std::vector<bool> v2(a);
+ static_assert(v2.size() == 0);
+ static_assert(v2.capacity() == 0);
+
+ constexpr Alloc<bool> aa(10);
+ constexpr std::vector<bool, Alloc<bool>> v3(aa);
+ static_assert(v3.size() == 0);
+ static_assert(v3.capacity() == 0);
+ static_assert(v3.get_allocator() == aa);
+}
+
+constexpr bool
+default_constructor_function_scope()
+{
+ // vector()
+
+ std::vector<bool> v1;
+ VERIFY(v1.size() == 0);
+ VERIFY(v1.capacity() == 0);
+
+ // vector(const Allocator&)
+
+ const std::allocator<bool> a;
+ std::vector<bool> v2(a);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ const Alloc<bool> aa(10);
+ std::vector<bool, Alloc<bool>> v3(aa);
+ VERIFY(v3.size() == 0);
+ VERIFY(v3.capacity() == 0);
+ VERIFY(v3.get_allocator() == aa);
+
+ return true;
+}
+
+static_assert( default_constructor_function_scope() );
+
+constexpr bool
+sequence_constructors()
+{
+ // vector(size_type, const Allocator& = Allocator())
+
+ std::vector<bool> v0(0);
+ VERIFY(v0.size() == 0);
+
+ std::vector<bool> v1(1);
+ VERIFY(v1.size() == 1);
+
+ std::vector<bool> v2(2);
+ VERIFY(v2.size() == 2);
+
+ std::vector<bool> v50(50);
+ VERIFY(v50.size() == 50);
+
+ const std::allocator<bool> a;
+ std::vector<bool> a0(0, a);
+ VERIFY(a0.size() == 0);
+
+ std::vector<bool> a1(1, a);
+ VERIFY(a1.size() == 1);
+
+ std::vector<bool> a2(2, a);
+ VERIFY(a2.size() == 2);
+
+ std::vector<bool> a50(50, a);
+ VERIFY(a50.size() == 50);
+
+ const Alloc<bool> la(10);
+ std::vector<bool, Alloc<bool>> l0(0, la);
+ VERIFY(l0.size() == 0);
+ VERIFY(l0.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l1(1, la);
+ VERIFY(l1.size() == 1);
+ VERIFY(l1.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l2(2, la);
+ VERIFY(l2.size() == 2);
+ VERIFY(l2.get_allocator() == la);
+
+ std::vector<bool, Alloc<bool>> l50(50, la);
+ VERIFY(l50.size() == 50);
+ VERIFY(l50.get_allocator() == la);
+
+ // vector(size_type, const T&, const Allocator& = Allocator())
+
+ std::vector<bool> v3(3, true);
+ VERIFY(v3.size() == 3);
+ VERIFY(v3[0] == true && v3[2] == true);
+
+ std::vector<bool> a3(3, false, a);
+ VERIFY(a3.size() == 3);
+ VERIFY(a3[0] == false && a3[2] == false);
+
+ std::vector<bool, Alloc<bool>> l3(3, true, la);
+ VERIFY(l3.size() == 3);
+ VERIFY(l3[0] == true && l3[2] == true);
+ VERIFY(l3.get_allocator() == la);
+
+ return true;
+}
+
+static_assert(sequence_constructors());
+
+constexpr bool
+iterator_range_constructor()
+{
+ // vector(InputIterator, InputIterator, const Allocator& = Allocator())
+
+ short range[3] = { true, false, true };
+
+ std::vector<bool> v0(std::begin(range), std::end(range));
+ VERIFY(v0.size() == std::size(range));
+ VERIFY(v0[0] == true && v0[1] == false && v0[2] == true);
+
+ const Alloc<bool> a(5);
+ std::vector<bool, Alloc<bool>> l0(std::begin(range), std::end(range), a);
+ VERIFY(l0.size() == std::size(range));
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == true && l0[1] == false && l0[2] == true);
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ std::vector<bool> v1(input_iterator(3), input_iterator());
+ VERIFY(v1.size() == 3);
+ VERIFY(v1[0] == true && v1[1] == false && v1[2] == true);
+
+ std::vector<bool, Alloc<bool>> l1(input_iterator(2), input_iterator(), a);
+ VERIFY(l1.size() == 2);
+ VERIFY(l1.get_allocator() == a);
+ VERIFY(l1[0] == false && l1[1] == true);
+
+ return true;
+}
+
+static_assert(iterator_range_constructor());
+
+constexpr bool
+initializer_list_constructor()
+{
+ // vector(initializer_list<T>, const Allocator& = Allocator())
+
+ std::vector<bool> v0({ false, true, false });
+ VERIFY(v0.size() == 3);
+ VERIFY(v0[0] == false && v0[1] == true && v0[2] == false);
+
+ const Alloc<bool> a(5);
+ std::vector<bool, Alloc<bool>> l0({ true, false, false }, a);
+ VERIFY(l0.size() == 3);
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == true && l0[1] == false && l0[2] == false);
+
+ return true;
+}
+
+static_assert(initializer_list_constructor());
+
+constexpr bool
+copy_constructor()
+{
+ const std::vector<bool> v0({ 1, 0, 0, 1, 0, 1, 1, 0 });
+ const std::vector<bool, Alloc<bool>> l0({ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 });
+
+ // vector(const vector&)
+
+ std::vector<bool> v1(v0);
+ VERIFY( v1.size() == v0.size() );
+ VERIFY( v1[0] == v0[0] && v1[1] == v0[1] && v1[2] == v0[2] );
+ VERIFY( v1.get_allocator() == v0.get_allocator() );
+
+ const Alloc<bool> as(6);
+ std::vector<bool, Alloc<bool>> s1(3, true, as);
+ std::vector<bool, Alloc<bool>> s2(s1);
+ VERIFY( s2.size() == s1.size() );
+ VERIFY( s2.get_allocator().personality == -1 );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<bool> a(6);
+ std::vector<bool, Alloc<bool>> l1(l0, a);
+ VERIFY( l1.size() == l0.size() );
+ VERIFY( l1[0] == l0[0] && l1[1] == l0[1] && l1[2] == l0[2] );
+ VERIFY( l1.get_allocator() == a );
+ VERIFY( l1.get_allocator() != l0.get_allocator() );
+
+ return true;
+}
+
+static_assert(copy_constructor());
+
+constexpr bool
+move_constructor()
+{
+ const std::vector<bool> v0({ 1, 0, 0, 1, 0, 1, 1, 0 });
+ const std::vector<bool, Alloc<bool>> l0({ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 });
+
+ // vector(const vector&)
+
+ std::vector<bool> v1(v0);
+ std::vector<bool> v2(std::move(v1));
+ VERIFY( v2.size() == v0.size() );
+ VERIFY( v1.empty() );
+ VERIFY( v2[0] == v0[0] && v2[1] == v0[1] && v2[2] == v0[2] );
+ VERIFY( v2.get_allocator() == v0.get_allocator() );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<bool> a(6);
+ std::vector<bool, Alloc<bool>> l1(l0);
+ std::vector<bool, Alloc<bool>> l2(std::move(l1), a);
+ VERIFY( l2.size() == l0.size() );
+ VERIFY( l2[0] == l0[0] && l2[1] == l0[1] && l2[2] == l0[2] );
+ VERIFY( l2.get_allocator() == a );
+ VERIFY( l2.get_allocator() != l0.get_allocator() );
+
+ std::vector<bool, Alloc<bool>> l3(std::move(l2), a);
+ VERIFY( l3.size() == l0.size() );
+ VERIFY( l3[0] == l0[0] && l3[1] == l0[1] && l3[2] == l0[2] );
+ VERIFY( l3.get_allocator() == a );
+ VERIFY( l3.get_allocator() == l2.get_allocator() );
+
+ return true;
+}
+
+static_assert(move_constructor());
new file mode 100644
@@ -0,0 +1,102 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_iterators()
+{
+ std::vector<bool> v;
+ VERIFY( v.begin() == v.end() );
+ v.reserve(1);
+ VERIFY( v.begin() == v.end() );
+ v.resize(2);
+ VERIFY( v.begin() != v.end() );
+ VERIFY( v.cbegin() == v.begin() );
+ VERIFY( v.crbegin() == v.rbegin() );
+ VERIFY( v.cend() == v.end() );
+ VERIFY( v.crend() == v.rend() );
+
+ auto it = v.begin();
+ VERIFY( *it == v.front() );
+ VERIFY( it++ == v.begin() );
+ VERIFY( ++it == v.end() );
+ VERIFY( (it - 2) == v.begin() );
+ it -= 2;
+ it += 1;
+ VERIFY( (it + 1) == v.end() );
+
+ auto rit = v.rbegin();
+ VERIFY( *rit == v.back() );
+ VERIFY( rit++ == v.rbegin() );
+ VERIFY( ++rit == v.rend() );
+ VERIFY( (rit - 2) == v.rbegin() );
+ rit -= 2;
+ rit += 1;
+ VERIFY( (rit + 1) == v.rend() );
+
+ return true;
+}
+
+static_assert(test_iterators());
+
+constexpr bool
+test_access()
+{
+ std::vector<bool> v{1, 1, 0, 0, 1, 0, 1, 0, 1};
+ std::vector<bool>::reference r1 = v.at(1);
+ VERIFY( r1 );
+ std::vector<bool>::reference r2 = v[2];
+ VERIFY( ! r2 );
+ r1 = r2;
+ VERIFY( ! r1 );
+ VERIFY( ! v[1] );
+ r2 = true;
+ VERIFY( r2 );
+ VERIFY( v[2] );
+
+ const auto& vc = v;
+ VERIFY( vc.at(1) == false );
+ VERIFY( vc.at(1) == v.at(1) );
+ VERIFY( vc.at(1) == vc[1] );
+ VERIFY( vc.front() == vc[0] );
+ VERIFY( vc.back() == vc[2] );
+
+ return true;
+}
+
+static_assert(test_access());
+
+template<typename T = bool>
+ constexpr std::false_type
+ access_empty() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().at(0), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().back(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+static_assert( ! access_empty() );
+
+template<typename T = bool>
+ constexpr std::false_type
+ access_empty_front() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>()[0], true)>::value)
+ constexpr std::true_type
+ access_empty_front() { return {}; }
+
+template<typename T = bool>
+ requires (std::bool_constant<(std::vector<T>().front(), true)>::value)
+ constexpr std::true_type
+ access_empty_front() { return {}; }
+
+static_assert( ! access_empty_front() ); // { dg-error "ambiguous" "PR 103191" { target { ! debug-mode } } }
new file mode 100644
@@ -0,0 +1,216 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ using propagate_on_container_move_assignment = std::false_type;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+copy_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<bool> v1, v2;
+ v1 = v1;
+ v2 = v1;
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = v1;
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = v1;
+ VERIFY(v2.size() == 11);
+ VERIFY(v2.capacity() == capacity_for(50));
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(1)), va2(Alloc<bool>(2));
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(999);
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( copy_assign() );
+
+constexpr bool
+move_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<bool> v1, v2;
+ v1 = std::move(v1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 1);
+ VERIFY(v1.capacity() == 0);
+ VERIFY(v2.capacity() == capacity_for(1));
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(1)), va2(Alloc<bool>(2));
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(9);
+ va1.push_back(99);
+ va1.push_back(999);
+ va1.push_back(9999);
+ va2 = std::move(va1);
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( move_assign() );
+
+constexpr bool
+initializer_list_assign()
+{
+ std::vector<bool> v1;
+ v1 = {1, 0, 1};
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1 = {1, 0};
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1 = {1, 1, 0, 1, 1, 1, 0, 1, 1};
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1 = {1, 0, 0};
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( initializer_list_assign() );
+
+constexpr bool
+assign_iterator_range()
+{
+ std::vector<bool> v;
+
+ int arr[] = { 1, 2, 3, 4 };
+ v.assign(arr, arr+3);
+ VERIFY( v.size() == 3 );
+ v.reserve(5);
+ v.assign(arr, arr+3);
+ VERIFY( v.capacity() == capacity_for(5) );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ v.assign(input_iterator(9), input_iterator());
+ VERIFY( v.size() == 9 );
+
+ return true;
+}
+
+static_assert( assign_iterator_range() );
+
+constexpr bool
+assign_value()
+{
+ std::vector<bool> v1;
+ v1.assign(3, 8);
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign(2, 9);
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign(9, 10);
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1.assign(2, 9);
+ VERIFY( va1.size() == 2 );
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_value() );
+
+constexpr bool
+assign_initializer_list()
+{
+ std::vector<bool> v1;
+ v1.assign({0, 1, 0});
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign({1, 0});
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == capacity_for(3) );
+ v1.assign({1, 0, 0, 1, 1, 0, 0, 1, 1});
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == capacity_for(9) );
+
+ std::vector<bool, Alloc<bool>> va1(Alloc<bool>(111));
+ va1.assign({1, 1, 1});
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_initializer_list() );
new file mode 100644
@@ -0,0 +1,248 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+test_push_back()
+{
+ std::vector<bool> v;
+ std::vector<bool>::reference r = v.emplace_back("");
+ VERIFY( r == true );
+ v.emplace_back(r);
+ VERIFY( v.back() == true );
+ v.emplace_back(v.front());
+ VERIFY( v.back() == true );
+ v.resize(64);
+ v.emplace_back(v.back());
+ VERIFY( v.back() == false );
+ VERIFY( v.size() == 65 );
+ v.emplace_back(8);
+ VERIFY( v.size() == 66 );
+ VERIFY( v.back() == true );
+ v.emplace_back();
+ VERIFY( v.size() == 67 );
+ VERIFY( v.back() == false );
+
+ v.pop_back();
+ VERIFY( v.size() == 66 );
+ VERIFY( v.back() == true );
+ for (int i = 0, n = v.size(); i < n; ++i)
+ v.pop_back();
+ VERIFY( v.empty() );
+
+ v.push_back(true);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.push_back(v.front());
+ VERIFY( v.capacity() > v.size() );
+
+ std::vector<bool, Alloc<bool>> va;
+ va.push_back(true);
+ va.push_back(va.front());
+ VERIFY( va.size() == 2 );
+
+ return true;
+}
+
+static_assert( test_push_back() );
+
+template<typename T = bool>
+constexpr std::false_type
+pop_back_empty() { return {}; }
+
+template<typename T = bool>
+requires (std::bool_constant<(std::vector<T>().pop_back(), true)>::value)
+constexpr std::true_type
+pop_back_empty() { return {}; }
+
+static_assert( ! pop_back_empty() );
+
+constexpr bool
+test_insert_erase()
+{
+ std::vector<bool> v;
+
+ // vector::emplace(const_iterator, Args&&...)
+ auto p = v.emplace(v.begin());
+ VERIFY( p == v.begin() );
+ p = v.emplace(v.end(), '7');
+ VERIFY( p == --v.end() );
+
+ // vector::insert(const_iterator, const T&)
+ p = v.insert(v.begin(), *p);
+ VERIFY( p == v.begin() );
+ VERIFY( *p );
+ // vector::insert(const_iterator, T&&)
+ p = v.insert(v.end(), 1);
+ VERIFY( p == --v.end() );
+ v.insert(p, v.front());
+ v.insert(v.end(), v.back());
+ VERIFY( v.size() == 6 );
+ v.insert(v.end(), true);
+ VERIFY( v.size() == 7 );
+ VERIFY( v.back() == true );
+
+ // vector::insert(const_iterator, size_type, const T&)
+ v.insert(v.begin(), 2, v.front());
+ v.insert(v.end(), 3, 99);
+ VERIFY( v.size() == 12 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = bool;
+ using pointer = const bool*;
+ using reference = bool;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr bool operator*() const { return val % 2; }
+ constexpr const bool* operator->() const { return nullptr; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ // vector::insert(const_iterator, Iter, Iter);
+ v.insert(v.begin() + 2, input_iterator(), input_iterator());
+ VERIFY( v.size() == 12 );
+ v.insert(v.end() - 9, input_iterator(18), input_iterator());
+ VERIFY( v.size() == 30 );
+ short a[] = { false, true };
+ v.insert(v.end(), a, a + 2);
+ VERIFY( v.size() == 32 );
+
+ // vector::insert(const_iterator, initializer_list<T>)
+ v.insert(v.begin(), {1,1,1});
+ VERIFY( v.size() == 35 );
+
+ // vector::erase(const_iterator)
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 34 );
+ VERIFY( v.back() == false );
+ v.erase(v.begin());
+ v.erase(v.begin() + 1);
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 31 );
+
+ // vector::erase(const_iterator, const_iterator)
+ v.erase(v.begin(), v.begin());
+ v.erase(v.end(), v.end());
+ v.erase(v.begin(), v.begin() + 1);
+ VERIFY( v.size() == 30 );
+ v.erase(v.begin() + 2, v.end() - 2);
+ VERIFY( v.size() == 4 );
+ v.erase(v.begin(), v.end());
+ VERIFY( v.empty() );
+ v.erase( v.begin(), v.begin() );
+ VERIFY( v.empty() );
+
+ v.insert(v.end(), 99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.end() - 1, v.front());
+ VERIFY( v.capacity() > v.size() );
+ v.insert(v.end(), 999);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.begin(), v.front());
+
+ std::vector<bool, Alloc<bool>> va;
+ va.insert(va.begin(), 99);
+ va.insert(va.begin(), va.front());
+ VERIFY( va.size() == 2 );
+ va.erase(va.begin());
+
+ return true;
+}
+
+static_assert( test_insert_erase() );
+
+constexpr std::size_t
+capacity_for(std::size_t n)
+{
+ std::size_t N = std::vector<bool>(1).capacity();
+ if (auto r = n % N)
+ return n - r + N;
+ return n;
+}
+
+constexpr bool
+test_clear()
+{
+ std::vector<bool> v0;
+ v0.clear();
+ VERIFY( v0.size() == 0 );
+ VERIFY( v0.capacity() == 0 );
+
+ std::vector<bool> v{1, 0, 0};
+ v.clear();
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == capacity_for(3) );
+
+ std::vector<bool, Alloc<bool>> va;
+ va.clear();
+ va.push_back(1);
+ va.clear();
+ va.clear();
+
+ return true;
+}
+
+static_assert( test_clear() );
+
+constexpr bool
+test_flip()
+{
+ std::vector<bool> v{1, 0, 0, 1, 0, 1, 1, 0};
+ v.flip();
+ VERIFY( !v[0] && v[1] && v[2] && !v[3] && v[4] && !v[5] && !v[6] && v[7] );
+ v[2].flip();
+ VERIFY( !v[2] );
+ v[2].flip();
+ VERIFY( v[2] );
+
+ return true;
+}
+
+static_assert( test_flip() );
+
+constexpr bool
+test_erasure()
+{
+ std::vector<bool> e{true,true,true,false,true,false};
+
+ auto n = std::erase(e, false);
+ VERIFY( n == 2 );
+ VERIFY( e.size() == 4 );
+ e[2] = false;
+ n = std::erase_if(e, [](std::vector<bool>::reference val) { return !val; });
+ VERIFY( n == 1 );
+ VERIFY( e.size() == 3 );
+
+ return true;
+}
+
+static_assert( test_erasure() );
@@ -24,11 +24,7 @@
#include <stdexcept>
#include <testsuite_hooks.h>
-#ifdef _GLIBCXX_DEBUG
- using std::_GLIBCXX_STD_C::_S_word_bit;
-#else
- using std::_S_word_bit;
-#endif
+using std::_S_word_bit;
inline void
check_cap_ge_size(const std::vector<bool>& x)
new file mode 100644
@@ -0,0 +1,66 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <utility>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_std_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool> v2 = {false, true};
+
+ std::swap(v1, v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == false);
+ VERIFY(v1.at(1) == true);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0]);
+ VERIFY(!v2[1]);
+ VERIFY(v2[2]);
+
+ return true;
+}
+
+static_assert(test_std_swap());
+
+constexpr bool
+test_member_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool> v2 = {false, true};
+
+ v1.swap(v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == false);
+ VERIFY(v1.at(1) == true);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0]);
+ VERIFY(!v2[1]);
+ VERIFY(v2[2]);
+
+ return true;
+}
+
+static_assert(test_member_swap());
+
+constexpr bool
+test_reference_swap()
+{
+ std::vector<bool> v1 = {true, false, true};
+ std::vector<bool>::swap(v1[0], v1[1]);
+
+ VERIFY(v1[0] == false);
+ VERIFY(v1[1] == true);
+ VERIFY(v1[2] == true);
+
+ return true;
+}
+
+static_assert(test_reference_swap());
new file mode 100644
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_empty()
+{
+ std::vector<int> v;
+ VERIFY( v.empty() );
+ v = {1};
+ VERIFY( !v.empty() );
+
+ return true;
+}
+
+static_assert( test_empty() );
+
+constexpr bool
+test_size()
+{
+ std::vector<int> v;
+ VERIFY( v.size() == 0 );
+ v = {1};
+ VERIFY( v.size() == 1 );
+
+ VERIFY( v.max_size() != 0 );
+
+ return true;
+}
+
+static_assert( test_size() );
+
+constexpr bool
+test_capacity()
+{
+ std::vector<int> v;
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == v.size() );
+ v = {1, 2, 3};
+ VERIFY( v.size() == 3 );
+ VERIFY( v.capacity() == v.size() );
+
+ return true;
+}
+
+static_assert( test_capacity() );
+
+constexpr bool
+test_resize()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(5);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(15, 6);
+ VERIFY( v.size() == 15 );
+ VERIFY( v[10] == 6 );
+
+ return true;
+}
+
+static_assert( test_resize() );
+
+constexpr bool
+test_reserve()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 9 );
+ v.resize(2);
+ VERIFY( v.size() == 2 );
+ VERIFY( v.capacity() == 9 );
+
+ return true;
+}
+
+static_assert( test_reserve() );
+
+constexpr bool
+test_shrink_to_fit()
+{
+ std::vector<int> v;
+ v.reserve(9);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == 0 );
+ v.reserve(9);
+ v.resize(5);
+ v.shrink_to_fit();
+ VERIFY( v.capacity() == v.size() );
+
+ return true;
+}
+
+static_assert( test_shrink_to_fit() );
@@ -16,12 +16,13 @@
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
-// { dg-do run { target c++2a } }
+// { dg-do compile { target c++2a } }
+// { dg-xfail-if "not supported" { debug-mode } }
#include <vector>
#include <testsuite_hooks.h>
-void
+constexpr bool
test01()
{
std::vector<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
@@ -47,24 +48,26 @@ test01()
struct E
{
- bool operator==(E) { return true; }
+ constexpr bool operator==(E) const { return true; }
};
static_assert( ! std::totally_ordered<std::vector<E>> );
static_assert( ! std::three_way_comparable<E> );
static_assert( ! std::three_way_comparable<std::vector<E>> );
+
+ return true;
}
-void
+constexpr bool
test02()
{
struct W
{
int value = 0;
- bool operator==(W rhs) const noexcept
+ constexpr bool operator==(W rhs) const noexcept
{ return (value | 1) == (rhs.value | 1); }
- std::weak_ordering
+ constexpr std::weak_ordering
operator<=>(W rhs) const noexcept
{ return (value | 1) <=> (rhs.value | 1); }
};
@@ -75,23 +78,25 @@ test02()
static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
VERIFY( c1 == c2 );
VERIFY( std::is_eq(c1 <=> c2) );
+
+ return true;
}
-void
+constexpr bool
test03()
{
struct P
{
int value = 0;
- bool operator==(P rhs) const noexcept
+ constexpr bool operator==(P rhs) const noexcept
{
if (value < 0 || rhs.value < 0)
return false;
return value == rhs.value;
}
- std::partial_ordering
+ constexpr std::partial_ordering
operator<=>(P rhs) const noexcept
{
if (value < 0 || rhs.value < 0)
@@ -106,16 +111,18 @@ test03()
static_assert( std::three_way_comparable<P> );
static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
VERIFY( (c <=> c) == std::partial_ordering::unordered );
+
+ return true;
}
-void
+constexpr bool
test04()
{
struct L
{
int value = 0;
- bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ constexpr bool operator<(L rhs) const noexcept { return value < rhs.value; }
};
static_assert( std::totally_ordered<std::vector<L>> );
@@ -123,9 +130,11 @@ test04()
std::vector<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
VERIFY( std::is_lt(c <=> d) );
+
+ return true;
}
-void
+constexpr bool
test05()
{
// vector iterators are random access, so should support <=>
@@ -148,14 +157,12 @@ test05()
static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
std::strong_ordering> );
+
+ return true;
}
-int
-main()
-{
- test01();
- test02();
- test03();
- test04();
- test05();
-}
+static_assert( test01() );
+static_assert( test02() );
+static_assert( test03() );
+static_assert( test04() );
+static_assert( test05() );
@@ -31,20 +31,18 @@ void test01()
{
X x[1];
// Should not be able to create vector using uninitialized_copy:
- std::vector<X> v1{x, x+1}; // { dg-error "here" }
-
- // Should not be able to create vector using uninitialized_fill_n:
- std::vector<X> v2{2u, X{}}; // { dg-error "here" }
+ std::vector<X> v1{x, x+1}; // { dg-error "here" "" { target c++17_down } }
+ // { dg-error "deleted function 'X::X" "" { target c++20 } 0 }
}
void test02()
{
-#if __cplusplus >= 201703L
struct Y : X { };
- // Can create initializer_list<Y> with C++17 guaranteed copy elision,
- // but shouldn't be able to copy from it with uninitialized_copy:
- std::vector<Y> v3{Y{}, Y{}, Y{}}; // { dg-error "here" "" { target c++17 } }
-#endif
+
+ // Should not be able to create vector using uninitialized_fill_n:
+ std::vector<Y> v2{2u, Y{}}; // { dg-error "here" "" { target c++17_down } }
+ // { dg-error "deleted function .*Y::Y" "" { target c++20 } 0 }
}
// { dg-error "must be constructible from input type" "" { target *-*-* } 0 }
+// { dg-prune-output "construct_at" }
new file mode 100644
@@ -0,0 +1,39 @@
+// Copyright (C) 2019-2021 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 { target c++17 } }
+
+#include <vector>
+
+// PR libstdc++/89164
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+};
+
+void test03()
+{
+ // Can create initializer_list<Y> with C++17 guaranteed copy elision,
+ // but shouldn't be able to copy from it with uninitialized_copy:
+ std::vector<X> v3{X{}, X{}, X{}}; // { dg-error "here" "" { target c++17_only } }
+ // { dg-error "deleted function .*X::X" "" { target c++20 } 0 }
+}
+
+// { dg-error "must be constructible from input type" "" { target *-*-* } 0 }
+// { dg-prune-output "construct_at" }
new file mode 100644
@@ -0,0 +1,279 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr Alloc select_on_container_copy_construction() const
+ { return Alloc(-1); }
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+namespace default_constructor_global_scope
+{
+ constexpr std::vector<int> v1;
+ static_assert(v1.size() == 0);
+ static_assert(v1.capacity() == 0);
+
+ constexpr std::allocator<int> a;
+ constexpr std::vector<int> v2(a);
+ static_assert(v2.size() == 0);
+ static_assert(v2.capacity() == 0);
+
+ constexpr Alloc<int> aa(10);
+ constexpr std::vector<int, Alloc<int>> v3(aa);
+ static_assert(v3.size() == 0);
+ static_assert(v3.capacity() == 0);
+ static_assert(v3.get_allocator() == aa);
+}
+
+constexpr bool
+default_constructor_function_scope()
+{
+ // vector()
+
+ std::vector<int> v1;
+ VERIFY(v1.size() == 0);
+ VERIFY(v1.capacity() == 0);
+
+ // vector(const Allocator&)
+
+ const std::allocator<int> a;
+ std::vector<int> v2(a);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ const Alloc<long> aa(10);
+ std::vector<long, Alloc<long>> v3(aa);
+ VERIFY(v3.size() == 0);
+ VERIFY(v3.capacity() == 0);
+ VERIFY(v3.get_allocator() == aa);
+
+ return true;
+}
+
+static_assert( default_constructor_function_scope() );
+
+constexpr bool
+sequence_constructors()
+{
+ // vector(size_type, const Allocator& = Allocator())
+
+ std::vector<int> v0(0);
+ VERIFY(v0.size() == 0);
+
+ std::vector<int> v1(1);
+ VERIFY(v1.size() == 1);
+
+ std::vector<int> v2(2);
+ VERIFY(v2.size() == 2);
+
+ std::vector<int> v50(50);
+ VERIFY(v50.size() == 50);
+
+ const std::allocator<int> a;
+ std::vector<int> a0(0, a);
+ VERIFY(a0.size() == 0);
+
+ std::vector<int> a1(1, a);
+ VERIFY(a1.size() == 1);
+
+ std::vector<int> a2(2, a);
+ VERIFY(a2.size() == 2);
+
+ std::vector<int> a50(50, a);
+ VERIFY(a50.size() == 50);
+
+ const Alloc<long> la(10);
+ std::vector<long, Alloc<long>> l0(0, la);
+ VERIFY(l0.size() == 0);
+ VERIFY(l0.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l1(1, la);
+ VERIFY(l1.size() == 1);
+ VERIFY(l1.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l2(2, la);
+ VERIFY(l2.size() == 2);
+ VERIFY(l2.get_allocator() == la);
+
+ std::vector<long, Alloc<long>> l50(50, la);
+ VERIFY(l50.size() == 50);
+ VERIFY(l50.get_allocator() == la);
+
+ // vector(size_type, const T&, const Allocator& = Allocator())
+
+ std::vector<int> v3(3, 4);
+ VERIFY(v3.size() == 3);
+ VERIFY(v3[0] == 4 && v3[2] == 4);
+
+ std::vector<int> a3(3, 5, a);
+ VERIFY(a3.size() == 3);
+ VERIFY(a3[0] == 5 && a3[2] == 5);
+
+ std::vector<long, Alloc<long>> l3(3, 6, la);
+ VERIFY(l3.size() == 3);
+ VERIFY(l3[0] == 6 && l3[2] == 6);
+ VERIFY(l3.get_allocator() == la);
+
+ return true;
+}
+
+static_assert(sequence_constructors());
+
+constexpr bool
+iterator_range_constructor()
+{
+ // vector(InputIterator, InputIterator, const Allocator& = Allocator())
+
+ short range[3] = { 1, 2, 3 };
+
+ std::vector<int> v0(std::begin(range), std::end(range));
+ VERIFY(v0.size() == std::size(range));
+ VERIFY(v0[0] == 1 && v0[1] == 2 && v0[2] == 3);
+
+ const Alloc<long> a(5);
+ std::vector<long, Alloc<long>> l0(std::begin(range), std::end(range), a);
+ VERIFY(l0.size() == std::size(range));
+ VERIFY(l0.get_allocator() == a);
+ VERIFY(l0[0] == 1 && l0[1] == 2 && l0[2] == 3);
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ std::vector<int> v1(input_iterator(3), input_iterator());
+ VERIFY(v1.size() == 3);
+ VERIFY(v1[0] == 3 && v1[1] == 2 && v1[2] == 1);
+
+ std::vector<long, Alloc<long>> l1(input_iterator(2), input_iterator(), a);
+ VERIFY(l1.size() == 2);
+ VERIFY(l1.get_allocator() == a);
+ VERIFY(l1[0] == 2 && l1[1] == 1);
+
+ return true;
+}
+
+static_assert(iterator_range_constructor());
+
+constexpr bool
+initializer_list_constructor()
+{
+ // vector(initializer_list<T>, const Allocator& = Allocator())
+
+ std::vector<int> v0({ 1, 2, 3 });
+ VERIFY(v0.size() == 3);
+ VERIFY(v0[0] == 1 && v0[1] == 2 && v0[2] == 3);
+
+ const Alloc<long> a(5);
+ std::vector<long, Alloc<long>> l0({ 1, 2, 3 }, a);
+ VERIFY(l0.size() == 3);
+ VERIFY(l0.get_allocator() == a);
+
+ return true;
+}
+
+static_assert(initializer_list_constructor());
+
+constexpr bool
+copy_constructor()
+{
+ const std::vector<int> v0({ 1, 2, 3 });
+ const std::vector<long, Alloc<long>> l0({ 4, 5, 6 });
+
+ // vector(const vector&)
+
+ std::vector<int> v1(v0);
+ VERIFY( v1.size() == v0.size() );
+ VERIFY( v1[0] == v0[0] && v1[1] == v0[1] && v1[2] == v0[2] );
+ VERIFY( v1.get_allocator() == v0.get_allocator() );
+
+ const Alloc<short> as(6);
+ std::vector<short, Alloc<short>> s1(3, short(2), as);
+ std::vector<short, Alloc<short>> s2(s1);
+ VERIFY( s2.size() == s1.size() );
+ VERIFY( s2.get_allocator().personality == -1 );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<long> a(6);
+ std::vector<long, Alloc<long>> l1(l0, a);
+ VERIFY( l1.size() == l0.size() );
+ VERIFY( l1[0] == l0[0] && l1[1] == l0[1] && l1[2] == l0[2] );
+ VERIFY( l1.get_allocator() == a );
+ VERIFY( l1.get_allocator() != l0.get_allocator() );
+
+ return true;
+}
+
+static_assert(copy_constructor());
+
+constexpr bool
+move_constructor()
+{
+ const std::vector<int> v0({ 1, 2, 3 });
+ const std::vector<long, Alloc<long>> l0({ 4, 5, 6 });
+
+ // vector(const vector&)
+
+ std::vector<int> v1(v0);
+ std::vector<int> v2(std::move(v1));
+ VERIFY( v2.size() == v0.size() );
+ VERIFY( v1.empty() );
+ VERIFY( v2[0] == v0[0] && v2[1] == v0[1] && v2[2] == v0[2] );
+ VERIFY( v2.get_allocator() == v0.get_allocator() );
+
+ // vector(const vector&, const Allocator&)
+
+ const Alloc<long> a(6);
+ std::vector<long, Alloc<long>> l1(l0);
+ std::vector<long, Alloc<long>> l2(std::move(l1), a);
+ VERIFY( l2.size() == l0.size() );
+ VERIFY( l2[0] == l0[0] && l2[1] == l0[1] && l2[2] == l0[2] );
+ VERIFY( l2.get_allocator() == a );
+ VERIFY( l2.get_allocator() != l0.get_allocator() );
+
+ std::vector<long, Alloc<long>> l3(std::move(l2), a);
+ VERIFY( l3.size() == l0.size() );
+ VERIFY( l3[0] == l0[0] && l3[1] == l0[1] && l3[2] == l0[2] );
+ VERIFY( l3.get_allocator() == a );
+ VERIFY( l3.get_allocator() == l2.get_allocator() );
+
+ return true;
+}
+
+static_assert(move_constructor());
new file mode 100644
@@ -0,0 +1,26 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_data()
+{
+ std::vector<int> v;
+ VERIFY( v.data() == nullptr );
+ v.reserve(1);
+ VERIFY( v.data() != nullptr );
+ const std::vector<int> v2{1,3,5,9};
+ VERIFY( v.data() != v2.data() );
+ VERIFY( v2.data()[2] == 5 );
+
+ v = v2;
+ VERIFY( v.data() != v2.data() );
+ VERIFY( v.data()[1] == 3 );
+
+ return true;
+}
+
+static_assert(test_data());
new file mode 100644
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_iterators()
+{
+ std::vector<int> v;
+ VERIFY( v.begin() == v.end() );
+ v.reserve(1);
+ VERIFY( v.begin() == v.end() );
+ v.resize(2);
+ VERIFY( v.begin() != v.end() );
+ VERIFY( v.cbegin() == v.begin() );
+ VERIFY( v.crbegin() == v.rbegin() );
+ VERIFY( v.cend() == v.end() );
+ VERIFY( v.crend() == v.rend() );
+
+ auto it = v.begin();
+ VERIFY( &*it == &v.front() );
+ VERIFY( it++ == v.begin() );
+ VERIFY( ++it == v.end() );
+ VERIFY( (it - 2) == v.begin() );
+ it -= 2;
+ it += 1;
+ VERIFY( (it + 1) == v.end() );
+
+ auto rit = v.rbegin();
+ VERIFY( &*rit == &v.back() );
+ VERIFY( rit++ == v.rbegin() );
+ VERIFY( ++rit == v.rend() );
+ VERIFY( (rit - 2) == v.rbegin() );
+ rit -= 2;
+ rit += 1;
+ VERIFY( (rit + 1) == v.rend() );
+
+ return true;
+}
+
+static_assert(test_iterators());
+
+constexpr bool
+test_access()
+{
+ std::vector<int> v{1, 2, 3};
+ VERIFY( v.at(1) == 2 );
+ VERIFY( v[2] == 3 );
+ VERIFY( &v[2] == &v.at(2) );
+ VERIFY( &v.front() == &v[0] );
+ VERIFY( &v.back() == &v[2] );
+
+ const auto& vc = v;
+ VERIFY( vc.at(1) == 2 );
+ VERIFY( &vc.at(1) == &v.at(1) );
+ VERIFY( &vc.at(1) == &vc[1] );
+ VERIFY( &vc.front() == &vc[0] );
+ VERIFY( &vc.back() == &vc[2] );
+
+ return true;
+}
+
+static_assert(test_access());
+
+template<typename T = int>
+ constexpr std::false_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().at(0), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>()[0], true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().front(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+template<typename T = int>
+ requires (std::bool_constant<(std::vector<T>().back(), true)>::value)
+ constexpr std::true_type
+ access_empty() { return {}; }
+
+static_assert( ! access_empty() );
new file mode 100644
@@ -0,0 +1,207 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ using propagate_on_container_move_assignment = std::false_type;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+copy_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<int> v1, v2;
+ v1 = v1;
+ v2 = v1;
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = v1;
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = v1;
+ VERIFY(v2.size() == 11);
+ VERIFY(v2.capacity() == 50);
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(1)), va2(Alloc<int>(2));
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(999);
+ va2 = va1;
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( copy_assign() );
+
+constexpr bool
+move_assign()
+{
+ // vector::operator=(const vector&)
+
+ std::vector<int> v1, v2;
+ v1 = std::move(v1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 0);
+ VERIFY(v2.capacity() == 0);
+
+ for (int i = 0; i < 10; ++i)
+ v1.push_back(i);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 10);
+ v2.reserve(50);
+ v1.push_back(1);
+ v2 = std::move(v1);
+ VERIFY(v2.size() == 1);
+ VERIFY(v1.capacity() == 0);
+ VERIFY(v2.capacity() == 1);
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(1)), va2(Alloc<int>(2));
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+ va1.push_back(9);
+ va1.push_back(99);
+ va1.push_back(999);
+ va1.push_back(9999);
+ va2 = std::move(va1);
+ va2 = std::move(va1);
+ VERIFY( va2.get_allocator().personality == 2 );
+
+ return true;
+}
+
+static_assert( move_assign() );
+
+constexpr bool
+initializer_list_assign()
+{
+ std::vector<int> v1;
+ v1 = {1, 2, 3};
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1 = {1, 2};
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1 = {1, 2, 3};
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( initializer_list_assign() );
+
+constexpr bool
+assign_iterator_range()
+{
+ std::vector<int> v;
+
+ int arr[] = { 1, 2, 3, 4 };
+ v.assign(arr, arr+3);
+ VERIFY( v.size() == 3 );
+ v.reserve(5);
+ v.assign(arr, arr+3);
+ VERIFY( v.capacity() == 5 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ v.assign(input_iterator(9), input_iterator());
+ VERIFY( v.size() == 9 );
+
+ return true;
+}
+
+static_assert( assign_iterator_range() );
+
+constexpr bool
+assign_value()
+{
+ std::vector<int> v1;
+ v1.assign(3, 8);
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign(2, 9);
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign(9, 10);
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1.assign(2, 9);
+ VERIFY( va1.size() == 2 );
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_value() );
+
+constexpr bool
+assign_initializer_list()
+{
+ std::vector<int> v1;
+ v1.assign({1, 2, 3});
+ VERIFY( v1.size() == 3 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign({1, 2});
+ VERIFY( v1.size() == 2 );
+ VERIFY( v1.capacity() == 3 );
+ v1.assign({1, 2, 3, 4, 5, 6, 7, 8, 9});
+ VERIFY( v1.size() == 9 );
+ VERIFY( v1.capacity() == 9 );
+
+ std::vector<int, Alloc<int>> va1(Alloc<int>(111));
+ va1.assign({1, 2, 3});
+ VERIFY( va1.get_allocator().personality == 111 );
+
+ return true;
+}
+
+static_assert( assign_initializer_list() );
new file mode 100644
@@ -0,0 +1,226 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct Alloc : std::allocator<T>
+{
+ using std::allocator<T>::allocator;
+
+ constexpr explicit Alloc(int p) : personality(p) { }
+
+ template<typename U>
+ constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
+
+ int personality = 0;
+
+ constexpr bool operator==(const Alloc& a) const noexcept
+ { return personality == a.personality; }
+};
+
+constexpr bool
+test_push_back()
+{
+ std::vector<int> v;
+ int& r = v.emplace_back(7);
+ VERIFY( r == 7 );
+ VERIFY( &r == &v.front() );
+ v.emplace_back(r);
+ v.emplace_back(v.front());
+ v.emplace_back(v.back());
+ VERIFY( v.size() == 4 );
+ v.emplace_back(8);
+ VERIFY( v.size() == 5 );
+ VERIFY( v.back() == 8 );
+
+ v.pop_back();
+ VERIFY( v.size() == 4 );
+ VERIFY( v.back() == 7 );
+ v.pop_back();
+ v.pop_back();
+ v.pop_back();
+ v.pop_back();
+ VERIFY( v.empty() );
+
+ v.push_back(99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.push_back(v.front());
+ VERIFY( v.capacity() > v.size() );
+
+ std::vector<int, Alloc<int>> va;
+ va.push_back(99);
+ va.push_back(va.front());
+ VERIFY( va.size() == 2 );
+
+ return true;
+}
+
+static_assert( test_push_back() );
+
+template<typename T = int>
+constexpr std::false_type
+pop_back_empty() { return {}; }
+
+template<typename T = int>
+requires (std::bool_constant<(std::vector<T>().pop_back(), true)>::value)
+constexpr std::true_type
+pop_back_empty() { return {}; }
+
+static_assert( ! pop_back_empty() );
+
+constexpr bool
+test_insert_erase()
+{
+ std::vector<int> v;
+
+ // vector::emplace(const_iterator, Args&&...)
+ auto p = v.emplace(v.begin());
+ VERIFY( p == v.begin() );
+ p = v.emplace(v.end(), 7);
+ VERIFY( p == --v.end() );
+
+ // vector::insert(const_iterator, const T&)
+ p = v.insert(v.begin(), *p);
+ VERIFY( p == v.begin() );
+ VERIFY( *p == 7 );
+ VERIFY( &*p == &v.front() );
+ // vector::insert(const_iterator, T&&)
+ p = v.insert(v.end(), 1);
+ VERIFY( p == --v.end() );
+ v.insert(p, v.front());
+ v.insert(v.end(), v.back());
+ VERIFY( v.size() == 6 );
+ v.insert(v.end(), 8);
+ VERIFY( v.size() == 7 );
+ VERIFY( v.back() == 8 );
+
+ // vector::insert(const_iterator, size_type, const T&)
+ v.insert(v.begin(), 2, v.front());
+ v.insert(v.end(), 3, 99);
+ VERIFY( v.size() == 12 );
+
+ struct input_iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using pointer = const int*;
+ using reference = int;
+ using difference_type = int;
+
+ constexpr input_iterator() : val(0) { }
+ constexpr input_iterator(int i) : val(i) { }
+
+ constexpr input_iterator& operator++() { --val; return *this; }
+ constexpr input_iterator operator++(int) { return {val--}; }
+
+ constexpr int operator*() const { return val; }
+ constexpr const int* operator->() const { return &val; }
+
+ constexpr bool operator==(const input_iterator&) const = default;
+
+ int val;
+ };
+
+ // vector::insert(const_iterator, Iter, Iter);
+ v.insert(v.begin() + 2, input_iterator(), input_iterator());
+ VERIFY( v.size() == 12 );
+ v.reserve(13);
+ auto n = v.capacity() - v.size();
+ v.insert(v.end() - 9, input_iterator(n), input_iterator()); // no reallocation
+ VERIFY( v.size() == (12 + n) );
+ short a[] = { 84, 85 };
+ v.insert(v.end() - 1, a, a + 2); // reallocation needed
+ VERIFY( v.size() == (12 + n + 2) );
+ v.resize(32);
+
+ // vector::insert(const_iterator, initializer_list<T>)
+ v.insert(v.begin(), {1,2,3});
+ VERIFY( v.size() == 35 );
+
+ v.rbegin()[0] = 999;
+ v.rbegin()[1] = 888;
+
+ // vector::erase(const_iterator)
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 34 );
+ VERIFY( v.back() == 888 );
+ v.erase(v.begin());
+ v.erase(v.begin() + 1);
+ v.erase(v.end() - 1);
+ VERIFY( v.size() == 31 );
+
+ // vector::erase(const_iterator, const_iterator)
+ v.erase(v.begin(), v.begin());
+ v.erase(v.end(), v.end());
+ v.erase(v.begin(), v.begin() + 1);
+ VERIFY( v.size() == 30 );
+ v.erase(v.begin() + 2, v.end() - 2);
+ VERIFY( v.size() == 4 );
+ v.erase(v.begin(), v.end());
+ VERIFY( v.empty() );
+ v.erase( v.begin(), v.begin() );
+ VERIFY( v.empty() );
+
+ v.insert(v.end(), 99);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.end() - 1, v.front());
+ VERIFY( v.capacity() > v.size() );
+ v.insert(v.end(), 999);
+ for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
+ v.insert(v.begin(), v.front());
+
+ std::vector<int, Alloc<int>> va;
+ va.insert(va.begin(), 99);
+ va.insert(va.begin(), va.front());
+ VERIFY( va.size() == 2 );
+ va.erase(va.begin());
+
+ return true;
+}
+
+static_assert( test_insert_erase() );
+
+constexpr bool
+test_clear()
+{
+ std::vector<int> v0;
+ v0.clear();
+ VERIFY( v0.size() == 0 );
+ VERIFY( v0.capacity() == 0 );
+
+ std::vector<int> v{1, 10, 100};
+ v.clear();
+ VERIFY( v.size() == 0 );
+ VERIFY( v.capacity() == 3 );
+
+ std::vector<int, Alloc<int>> va;
+ va.clear();
+ va.push_back(1);
+ va.clear();
+ va.clear();
+
+ return true;
+}
+
+static_assert( test_clear() );
+
+constexpr bool
+test_erasure()
+{
+ const char* names[] = { "Vince", "Clarke", "Andy", "Bell" };
+ std::vector<const char*> e(std::begin(names), std::end(names));
+
+ auto n = std::erase(e, names[0]);
+ VERIFY( n == 1 );
+ VERIFY( e.size() == 3 );
+ n = std::erase_if(e, [](auto name) { return name[4] == '\0'; });
+ VERIFY( n == 2 );
+ VERIFY( e.size() == 1 );
+
+ return true;
+}
+
+static_assert( test_erasure() );
new file mode 100644
@@ -0,0 +1,51 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+// { dg-xfail-if "not supported" { debug-mode } }
+
+#include <vector>
+#include <utility>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_std_swap()
+{
+ std::vector<int> v1 = {1, 2, 3};
+ std::vector<int> v2 = {0, 1};
+
+ std::swap(v1, v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == 0);
+ VERIFY(v1.at(1) == 1);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0] == 1);
+ VERIFY(v2[1] == 2);
+ VERIFY(v2[2] == 3);
+
+ return true;
+}
+
+static_assert(test_std_swap());
+
+constexpr bool
+test_member_swap()
+{
+ std::vector<int> v1 = {1, 2, 3};
+ std::vector<int> v2 = {0, 1};
+
+ v1.swap(v2);
+
+ VERIFY(v1.size() == 2);
+ VERIFY(v1.at(0) == 0);
+ VERIFY(v1.at(1) == 1);
+
+ VERIFY(v2.size() == 3);
+ VERIFY(v2[0] == 1);
+ VERIFY(v2[1] == 2);
+ VERIFY(v2[2] == 3);
+
+ return true;
+}
+
+static_assert(test_member_swap());