Files
gcc/libstdc++-v3/include/bits/stl_bvector.h
Tomasz Kamiński ae54d8cb51 libstdc++: Define __cpp_lib_containers_ranges in appropriate headers [PR111055]
This is final piece of P1206R7, adding a feature test macros,
as range constructors and member operations are now implemented for
all containers and adaptors.

For consistency with the proposal, all new container operations and
helpers are now defined if __glibcxx_containers_ranges, instead
of __glibcxx_ranges_to_container.

	PR libstdc++/111055

libstdc++-v3/ChangeLog:

	* include/bits/version.def (containers_ranges): Define.
	* include/bits/version.h: Regenerate.
	* include/bits/ranges_base.h (__detail::__container_compatible_range)
	(__detail::__range_to_alloc_type, __detail::__range_mapped_type)
	(__detail::__range_key_type): Depend on __glibcxx_containers_ranges
	instead of __glibcxx_ranges_to_container.
	* include/bits/basic_string.h: Replace __glibcxx_ranges_to_container with
	__glibcxx_containers_ranges.
	* include/bits/cow_string.h: Likewise.
	* include/bits/deque.tcc: Likewise.
	* include/bits/forward_list.h: Likewise.
	* include/bits/stl_bvector.h: Likewise.
	* include/bits/stl_deque.h: Likewise.
	* include/bits/stl_list.h: Likewise.
	* include/bits/stl_map.h: Likewise.
	* include/bits/stl_multimap.h: Likewise.
	* include/bits/stl_multiset.h: Likewise.
	* include/bits/stl_queue.h: Likewise.
	* include/bits/stl_set.h: Likewise.
	* include/bits/stl_stack.h: Likewise.
	* include/bits/stl_vector.h: Likewise.
	* include/bits/unordered_map.h: Likewise.
	* include/bits/unordered_set.h: Likewise.
	* include/bits/vector.tcc: Likewise.
	* include/debug/deque: Likewise.
	* include/debug/forward_list: Likewise.
	* include/debug/list: Likewise.
	* include/debug/map.h: Likewise.
	* include/debug/multimap.h: Likewise.
	* include/debug/multiset.h: Likewise.
	* include/debug/set.h: Likewise.
	* include/debug/unordered_map: Likewise.
	* include/debug/unordered_set: Likewise.
	* include/debug/vector: Likewise.
	* include/std/deque: Provide __cpp_lib_containers_ranges.
	* include/std/forward_list: Likewise.
	* include/std/list: Likewise.
	* include/std/map: Likewise.
	* include/std/queue: Likewise.
	* include/std/set: Likewise.
	* include/std/stack: Likewise.
	* include/std/string: Likewise.
	* include/std/unordered_map: Likewise.
	* include/std/unordered_set: Likewise.
	* include/std/vector: Likewise.
	* testsuite/21_strings/basic_string/cons/from_range.cc: Test for value
	__cpp_lib_containers_ranges.
	* testsuite/23_containers/deque/cons/from_range.cc: Likewise.
	* testsuite/23_containers/forward_list/cons/from_range.cc: Likewise.
	* testsuite/23_containers/list/cons/from_range.cc: Likewise.
	* testsuite/23_containers/map/cons/from_range.cc: Likewise.
	* testsuite/23_containers/multimap/cons/from_range.cc: Likewise.
	* testsuite/23_containers/multiset/cons/from_range.cc: Likewise.
	* testsuite/23_containers/priority_queue/cons_from_range.cc: Likewise.
	* testsuite/23_containers/queue/cons_from_range.cc: Likewise.
	* testsuite/23_containers/set/cons/from_range.cc: Likewise.
	* testsuite/23_containers/stack/cons_from_range.cc: Likewise.
	* testsuite/23_containers/unordered_map/cons/from_range.cc: Likewise.
	* testsuite/23_containers/unordered_multimap/cons/from_range.cc: Likewise.
	* testsuite/23_containers/unordered_multiset/cons/from_range.cc: Likewise.
	* testsuite/23_containers/unordered_set/cons/from_range.cc: Likewise.
	* testsuite/23_containers/vector/bool/cons/from_range.cc: Likewise.
	* testsuite/23_containers/vector/cons/from_range.cc: Likewise.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-04-11 13:56:03 +02:00

1842 lines
48 KiB
C++

// vector<bool> specialization -*- C++ -*-
// Copyright (C) 2001-2025 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1996-1999
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
/** @file bits/stl_bvector.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{vector}
*/
#ifndef _STL_BVECTOR_H
#define _STL_BVECTOR_H 1
#ifndef _GLIBCXX_ALWAYS_INLINE
#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
#endif
#if __cplusplus >= 201103L
#include <initializer_list>
#include <bits/functional_hash.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
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
{
private:
template<typename, typename> friend class vector;
friend struct _Bit_iterator;
friend struct _Bit_const_iterator;
_GLIBCXX20_CONSTEXPR
_Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { }
_Bit_type * _M_p;
_Bit_type _M_mask;
_GLIBCXX20_CONSTEXPR
_Bit_reference(_Bit_type * __x, _Bit_type __y)
: _M_p(__x), _M_mask(__y) { }
public:
#if __cplusplus >= 201103L
_Bit_reference(const _Bit_reference&) = default;
#endif
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
operator bool() const _GLIBCXX_NOEXCEPT
{ return !!(*_M_p & _M_mask); }
_GLIBCXX20_CONSTEXPR
_Bit_reference&
operator=(bool __x) _GLIBCXX_NOEXCEPT
{
if (__x)
*_M_p |= _M_mask;
else
*_M_p &= ~_M_mask;
return *this;
}
#if __cplusplus > 202002L
constexpr const _Bit_reference&
operator=(bool __x) const noexcept
{
if (__x)
*_M_p |= _M_mask;
else
*_M_p &= ~_M_mask;
return *this;
}
#endif // C++23
_GLIBCXX20_CONSTEXPR
_Bit_reference&
operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT
{ return *this = bool(__x); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
bool
operator==(const _Bit_reference& __x) const
{ return bool(*this) == bool(__x); }
_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
friend void
swap(_Bit_reference __x, _Bit_reference __y) noexcept
{
bool __tmp = __x;
__x = __y;
__y = __tmp;
}
_GLIBCXX20_CONSTEXPR
friend void
swap(_Bit_reference __x, bool& __y) noexcept
{
bool __tmp = __x;
__x = __y;
__y = __tmp;
}
_GLIBCXX20_CONSTEXPR
friend void
swap(bool& __x, _Bit_reference __y) noexcept
{
bool __tmp = __x;
__x = __y;
__y = __tmp;
}
#endif
};
// Ignore warnings about std::iterator.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
struct _Bit_iterator_base
: public std::iterator<std::random_access_iterator_tag, bool>
{
_Bit_type * _M_p;
unsigned int _M_offset;
_GLIBCXX20_CONSTEXPR _GLIBCXX_ALWAYS_INLINE
void
_M_assume_normalized() const
{
#if __has_attribute(__assume__) && !defined(_GLIBCXX_CLANG)
unsigned int __ofst = _M_offset;
__attribute__ ((__assume__ (__ofst < unsigned(_S_word_bit))));
#endif
}
_GLIBCXX20_CONSTEXPR
_Bit_iterator_base(_Bit_type * __x, unsigned int __y)
: _M_p(__x), _M_offset(__y) { }
_GLIBCXX20_CONSTEXPR
void
_M_bump_up()
{
_M_assume_normalized();
if (_M_offset++ == int(_S_word_bit) - 1)
{
_M_offset = 0;
++_M_p;
}
}
_GLIBCXX20_CONSTEXPR
void
_M_bump_down()
{
_M_assume_normalized();
if (_M_offset-- == 0)
{
_M_offset = int(_S_word_bit) - 1;
--_M_p;
}
}
_GLIBCXX20_CONSTEXPR
void
_M_incr(ptrdiff_t __i)
{
_M_assume_normalized();
difference_type __n = __i + _M_offset;
_M_p += __n / int(_S_word_bit);
__n = __n % int(_S_word_bit);
if (__n < 0)
{
__n += int(_S_word_bit);
--_M_p;
}
_M_offset = static_cast<unsigned int>(__n);
}
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR bool
operator==(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{
__x._M_assume_normalized();
__y._M_assume_normalized();
return __x._M_p == __y._M_p && __x._M_offset == __y._M_offset;
}
#if __cpp_lib_three_way_comparison
[[nodiscard]]
friend constexpr strong_ordering
operator<=>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
noexcept
{
__x._M_assume_normalized();
__y._M_assume_normalized();
if (const auto __cmp = __x._M_p <=> __y._M_p; __cmp != 0)
return __cmp;
return __x._M_offset <=> __y._M_offset;
}
#else
_GLIBCXX_NODISCARD
friend bool
operator<(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{
__x._M_assume_normalized();
__y._M_assume_normalized();
return __x._M_p < __y._M_p
|| (__x._M_p == __y._M_p && __x._M_offset < __y._M_offset);
}
_GLIBCXX_NODISCARD
friend bool
operator!=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return !(__x == __y); }
_GLIBCXX_NODISCARD
friend bool
operator>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return __y < __x; }
_GLIBCXX_NODISCARD
friend bool
operator<=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return !(__y < __x); }
_GLIBCXX_NODISCARD
friend bool
operator>=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return !(__x < __y); }
#endif // three-way comparison
friend _GLIBCXX20_CONSTEXPR ptrdiff_t
operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{
__x._M_assume_normalized();
__y._M_assume_normalized();
return (int(_S_word_bit) * (__x._M_p - __y._M_p)
+ __x._M_offset - __y._M_offset);
}
};
#pragma GCC diagnostic pop
struct _Bit_iterator : public _Bit_iterator_base
{
typedef _Bit_reference reference;
#if __cplusplus > 201703L
typedef void pointer;
#else
typedef _Bit_reference* pointer;
#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 _GLIBCXX20_CONSTEXPR
reference
operator*() const
{
_M_assume_normalized();
return reference(_M_p, 1UL << _M_offset);
}
_GLIBCXX20_CONSTEXPR
iterator&
operator++()
{
_M_bump_up();
return *this;
}
_GLIBCXX20_CONSTEXPR
iterator
operator++(int)
{
iterator __tmp = *this;
_M_bump_up();
return __tmp;
}
_GLIBCXX20_CONSTEXPR
iterator&
operator--()
{
_M_bump_down();
return *this;
}
_GLIBCXX20_CONSTEXPR
iterator
operator--(int)
{
iterator __tmp = *this;
_M_bump_down();
return __tmp;
}
_GLIBCXX20_CONSTEXPR
iterator&
operator+=(difference_type __i)
{
_M_incr(__i);
return *this;
}
_GLIBCXX20_CONSTEXPR
iterator&
operator-=(difference_type __i)
{
*this += -__i;
return *this;
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator[](difference_type __i) const
{ return *(*this + __i); }
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR iterator
operator+(const iterator& __x, difference_type __n)
{
iterator __tmp = __x;
__tmp += __n;
return __tmp;
}
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR iterator
operator+(difference_type __n, const iterator& __x)
{ return __x + __n; }
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR iterator
operator-(const iterator& __x, difference_type __n)
{
iterator __tmp = __x;
__tmp -= __n;
return __tmp;
}
};
struct _Bit_const_iterator : public _Bit_iterator_base
{
typedef bool reference;
typedef bool const_reference;
#if __cplusplus > 201703L
typedef void pointer;
#else
typedef const bool* pointer;
#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 _GLIBCXX20_CONSTEXPR
const_reference
operator*() const
{
_M_assume_normalized();
return _Bit_reference(_M_p, 1UL << _M_offset);
}
_GLIBCXX20_CONSTEXPR
const_iterator&
operator++()
{
_M_bump_up();
return *this;
}
_GLIBCXX20_CONSTEXPR
const_iterator
operator++(int)
{
const_iterator __tmp = *this;
_M_bump_up();
return __tmp;
}
_GLIBCXX20_CONSTEXPR
const_iterator&
operator--()
{
_M_bump_down();
return *this;
}
_GLIBCXX20_CONSTEXPR
const_iterator
operator--(int)
{
const_iterator __tmp = *this;
_M_bump_down();
return __tmp;
}
_GLIBCXX20_CONSTEXPR
const_iterator&
operator+=(difference_type __i)
{
_M_incr(__i);
return *this;
}
_GLIBCXX20_CONSTEXPR
const_iterator&
operator-=(difference_type __i)
{
*this += -__i;
return *this;
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator[](difference_type __i) const
{ return *(*this + __i); }
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR const_iterator
operator+(const const_iterator& __x, difference_type __n)
{
const_iterator __tmp = __x;
__tmp += __n;
return __tmp;
}
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR const_iterator
operator-(const const_iterator& __x, difference_type __n)
{
const_iterator __tmp = __x;
__tmp -= __n;
return __tmp;
}
_GLIBCXX_NODISCARD
friend _GLIBCXX20_CONSTEXPR const_iterator
operator+(difference_type __n, const const_iterator& __x)
{ return __x + __n; }
};
template<typename _Alloc>
struct _Bvector_base
{
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
rebind<_Bit_type>::other _Bit_alloc_type;
typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type>
_Bit_alloc_traits;
typedef typename _Bit_alloc_traits::pointer _Bit_pointer;
struct _Bvector_impl_data
{
#if !_GLIBCXX_INLINE_VERSION
_Bit_iterator _M_start;
#else
// We don't need the offset field for the start, it's always zero.
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
{
*this = __x;
__x._M_reset();
}
#endif
_GLIBCXX20_CONSTEXPR
void
_M_reset() _GLIBCXX_NOEXCEPT
{ *this = _Bvector_impl_data(); }
_GLIBCXX20_CONSTEXPR
void
_M_swap_data(_Bvector_impl_data& __x) _GLIBCXX_NOEXCEPT
{
// Do not use std::swap(_M_start, __x._M_start), etc as it loses
// information used by TBAA.
std::swap(*this, __x);
}
};
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)
#if __cpp_concepts && __glibcxx_type_trait_variable_templates
requires is_default_constructible_v<_Bit_alloc_type>
#endif
: _Bit_alloc_type()
{ }
_GLIBCXX20_CONSTEXPR
_Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT
: _Bit_alloc_type(__a)
{ }
#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
{
if (this->_M_end_of_storage)
return std::__addressof(this->_M_end_of_storage[-1]) + 1;
return 0;
}
};
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()); }
#if __cplusplus >= 201103L
_Bvector_base() = default;
#else
_Bvector_base() { }
#endif
_GLIBCXX20_CONSTEXPR
_Bvector_base(const allocator_type& __a)
: _M_impl(_Bit_alloc_type(__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)
{
_Bit_pointer __p = _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n));
#if __cpp_lib_is_constant_evaluated && __cpp_constexpr_dynamic_alloc
if (std::is_constant_evaluated())
{
__n = _S_nword(__n);
for (size_t __i = 0; __i < __n; ++__i)
std::construct_at(std::to_address(__p) + __i);
}
#endif
return __p;
}
_GLIBCXX20_CONSTEXPR
void
_M_deallocate()
{
if (_M_impl._M_start._M_p)
{
const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p;
_Bit_alloc_traits::deallocate(_M_impl,
_M_impl._M_end_of_storage - __n,
__n);
_M_impl._M_reset();
}
}
#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); }
};
/**
* @brief A specialization of vector for booleans which offers fixed time
* access to individual elements in any order.
*
* @ingroup sequences
* @headerfile vector
* @since C++98
*
* @tparam _Alloc Allocator type.
*
* Note that vector<bool> does not actually meet the requirements for being
* a container. This is because the reference and pointer types are not
* really references and pointers to bool. See DR96 for details. @see
* vector for function documentation.
*
* In some terminology a %vector can be described as a dynamic
* C-style array, it offers fast and efficient access to individual
* elements in any order and saves the user from worrying about
* memory and size allocation. Subscripting ( @c [] ) access is
* also provided as with C-style arrays.
*/
template<typename _Alloc>
class vector<bool, _Alloc> : protected _Bvector_base<_Alloc>
{
typedef _Bvector_base<_Alloc> _Base;
typedef typename _Base::_Bit_pointer _Bit_pointer;
typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits;
#if __cplusplus >= 201103L
friend struct std::hash<vector>;
# if __cplusplus > 201703L // || defined __STRICT_ANSI__
static_assert(is_same<typename _Alloc::value_type, bool>::value,
"std::vector must have the same value_type as its allocator");
# endif
#endif
public:
typedef bool value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Bit_reference reference;
typedef bool const_reference;
typedef _Bit_reference* pointer;
typedef const bool* const_pointer;
typedef _Bit_iterator iterator;
typedef _Bit_const_iterator const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef _Alloc allocator_type;
_GLIBCXX20_CONSTEXPR
allocator_type
get_allocator() const
{ return _Base::get_allocator(); }
protected:
using _Base::_M_allocate;
using _Base::_M_deallocate;
using _Base::_S_nword;
using _Base::_M_get_Bit_allocator;
public:
#if __cplusplus >= 201103L
vector() = default;
#else
vector() { }
#endif
_GLIBCXX20_CONSTEXPR
explicit
vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
: _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
explicit
vector(size_type __n, const bool& __value = bool(),
const allocator_type& __a = allocator_type())
#endif
: _Base(__a)
{
_M_initialize(__n);
_M_initialize_value(__value);
}
_GLIBCXX20_CONSTEXPR
vector(const vector& __x)
: _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator()))
{
const_iterator __xbegin = __x.begin(), __xend = __x.end();
_M_initialize(__x.size());
_M_copy_aligned(__xbegin, __xend, begin());
}
#if __cplusplus >= 201103L
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)
{
if (__x.get_allocator() == __a)
this->_M_move_data(std::move(__x));
else
{
_M_initialize(__x.size());
_M_copy_aligned(__x.begin(), __x.end(), begin());
__x.clear();
}
}
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)
{
_M_initialize(__x.size());
_M_copy_aligned(__x.begin(), __x.end(), begin());
}
_GLIBCXX20_CONSTEXPR
vector(initializer_list<bool> __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
{
_M_initialize_range(__l.begin(), __l.end(),
random_access_iterator_tag());
}
#endif
#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)
{
_M_initialize_range(__first, __last,
std::__iterator_category(__first));
}
#else
template<typename _InputIterator>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type())
: _Base(__a)
{
// Check whether it's an integral type. If so, it's not an iterator.
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
_M_initialize_dispatch(__first, __last, _Integral());
}
#endif
#if __glibcxx_containers_ranges // C++ >= 23
/**
* @brief Construct a vector from a range.
* @param __rg A range of values that are convertible to `value_type`.
* @since C++23
*/
template<__detail::__container_compatible_range<bool> _Rg>
constexpr
vector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
: _Base(__a)
{
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
{
_M_initialize(size_type(ranges::distance(__rg)));
ranges::copy(__rg, begin());
}
else
{
auto __first = ranges::begin(__rg);
const auto __last = ranges::end(__rg);
for (; __first != __last; ++__first)
emplace_back(*__first);
}
}
#endif
_GLIBCXX20_CONSTEXPR
~vector() _GLIBCXX_NOEXCEPT { }
_GLIBCXX20_CONSTEXPR
vector&
operator=(const vector& __x)
{
if (&__x == this)
return *this;
#if __cplusplus >= 201103L
if (_Bit_alloc_traits::_S_propagate_on_copy_assign())
{
if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator())
{
this->_M_deallocate();
std::__alloc_on_copy(_M_get_Bit_allocator(),
__x._M_get_Bit_allocator());
_M_initialize(__x.size());
}
else
std::__alloc_on_copy(_M_get_Bit_allocator(),
__x._M_get_Bit_allocator());
}
#endif
if (__x.size() > capacity())
{
this->_M_deallocate();
_M_initialize(__x.size());
}
this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(),
begin());
return *this;
}
#if __cplusplus >= 201103L
_GLIBCXX20_CONSTEXPR
vector&
operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move())
{
if (_Bit_alloc_traits::_S_propagate_on_move_assign()
|| this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator())
{
this->_M_deallocate();
this->_M_move_data(std::move(__x));
std::__alloc_on_move(_M_get_Bit_allocator(),
__x._M_get_Bit_allocator());
}
else
{
if (__x.size() > capacity())
{
this->_M_deallocate();
_M_initialize(__x.size());
}
this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(),
begin());
__x.clear();
}
return *this;
}
_GLIBCXX20_CONSTEXPR
vector&
operator=(initializer_list<bool> __l)
{
this->assign(__l.begin(), __l.end());
return *this;
}
#endif
// assign(), a generalized assignment member function. Two
// 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); }
#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)); }
#else
template<typename _InputIterator>
void
assign(_InputIterator __first, _InputIterator __last)
{
// Check whether it's an integral type. If so, it's not an iterator.
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
_M_assign_dispatch(__first, __last, _Integral());
}
#endif
#if __cplusplus >= 201103L
_GLIBCXX20_CONSTEXPR
void
assign(initializer_list<bool> __l)
{ _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); }
#endif
#if __glibcxx_containers_ranges // C++ >= 23
/**
* @brief Assign a range to the vector.
* @param __rg A range of values that are convertible to `value_type`.
* @pre `__rg` and `*this` do not overlap.
* @since C++23
*/
template<__detail::__container_compatible_range<bool> _Rg>
constexpr void
assign_range(_Rg&& __rg)
{
static_assert(assignable_from<bool&, ranges::range_reference_t<_Rg>>);
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
{
if (auto __n = size_type(ranges::distance(__rg)))
{
reserve(__n);
this->_M_impl._M_finish
= ranges::copy(std::forward<_Rg>(__rg), begin()).out;
}
else
clear();
}
else
{
clear();
auto __first = ranges::begin(__rg);
const auto __last = ranges::end(__rg);
for (; __first != __last; ++__first)
emplace_back(*__first);
}
}
#endif
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
begin() _GLIBCXX_NOEXCEPT
{ return iterator(this->_M_impl._M_start._M_p, 0); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
begin() const _GLIBCXX_NOEXCEPT
{ return const_iterator(this->_M_impl._M_start._M_p, 0); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
iterator
end() _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_finish; }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_iterator
end() const _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_finish; }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(end()); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(end()); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
{ return reverse_iterator(begin()); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
{ return const_reverse_iterator(begin()); }
#if __cplusplus >= 201103L
[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cbegin() const noexcept
{ return const_iterator(this->_M_impl._M_start._M_p, 0); }
[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_iterator
cend() const noexcept
{ return this->_M_impl._M_finish; }
[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crbegin() const noexcept
{ return const_reverse_iterator(end()); }
[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
const_reverse_iterator
crend() const noexcept
{ return const_reverse_iterator(begin()); }
#endif
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
size() const _GLIBCXX_NOEXCEPT
{ return size_type(end() - begin()); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
max_size() const _GLIBCXX_NOEXCEPT
{
const size_type __isize =
__gnu_cxx::__numeric_traits<difference_type>::__max
- int(_S_word_bit) + 1;
const size_type __asize
= _Bit_alloc_traits::max_size(_M_get_Bit_allocator());
return (__asize <= __isize / int(_S_word_bit)
? __asize * int(_S_word_bit) : __isize);
}
_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 _GLIBCXX20_CONSTEXPR
bool
empty() const _GLIBCXX_NOEXCEPT
{ return begin() == end(); }
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
operator[](size_type __n)
{
__glibcxx_requires_subscript(__n);
return _Bit_reference (this->_M_impl._M_start._M_p
+ __n / int(_S_word_bit),
1UL << __n % int(_S_word_bit));
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
operator[](size_type __n) const
{
__glibcxx_requires_subscript(__n);
return _Bit_reference (this->_M_impl._M_start._M_p
+ __n / int(_S_word_bit),
1UL << __n % int(_S_word_bit));
}
protected:
_GLIBCXX20_CONSTEXPR
void
_M_range_check(size_type __n) const
{
if (__n >= this->size())
__throw_out_of_range_fmt(__N("vector<bool>::_M_range_check: __n "
"(which is %zu) >= this->size() "
"(which is %zu)"),
__n, this->size());
}
public:
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
at(size_type __n)
{
_M_range_check(__n);
return (*this)[__n];
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
at(size_type __n) const
{
_M_range_check(__n);
return (*this)[__n];
}
_GLIBCXX20_CONSTEXPR
void
reserve(size_type __n)
{
if (__n > max_size())
__throw_length_error(__N("vector::reserve"));
if (capacity() < __n)
_M_reallocate(__n);
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
front()
{
__glibcxx_requires_nonempty();
return *begin();
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
front() const
{
__glibcxx_requires_nonempty();
return *begin();
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
reference
back()
{
__glibcxx_requires_nonempty();
return *(end() - 1);
}
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
const_reference
back() const
{
__glibcxx_requires_nonempty();
return *(end() - 1);
}
_GLIBCXX20_CONSTEXPR
void
push_back(bool __x)
{
if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr())
*this->_M_impl._M_finish++ = __x;
else
_M_insert_aux(end(), __x);
}
_GLIBCXX20_CONSTEXPR
void
swap(vector& __x) _GLIBCXX_NOEXCEPT
{
#if __cplusplus >= 201103L
__glibcxx_assert(_Bit_alloc_traits::propagate_on_container_swap::value
|| _M_get_Bit_allocator() == __x._M_get_Bit_allocator());
#endif
this->_M_impl._M_swap_data(__x._M_impl);
_Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(),
__x._M_get_Bit_allocator());
}
// [23.2.5]/1, third-to-last entry in synopsis listing
_GLIBCXX20_CONSTEXPR
static void
swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT
{
bool __tmp = __x;
__x = __y;
__y = __tmp;
}
_GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
insert(const_iterator __position, const bool& __x)
#else
insert(iterator __position, const bool& __x)
#endif
{
const difference_type __n = __position - begin();
if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()
&& __position == end())
*this->_M_impl._M_finish++ = __x;
else
_M_insert_aux(__position._M_const_cast(), __x);
return begin() + __n;
}
#if _GLIBCXX_USE_DEPRECATED
_GLIBCXX_DEPRECATED_SUGGEST("insert(position, false)")
iterator
insert(const_iterator __position)
{ return this->insert(__position._M_const_cast(), false); }
#endif
#if __cplusplus >= 201103L
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
_GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
difference_type __offset = __position - cbegin();
_M_insert_range(__position._M_const_cast(),
__first, __last,
std::__iterator_category(__first));
return begin() + __offset;
}
#else
template<typename _InputIterator>
void
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
// Check whether it's an integral type. If so, it's not an iterator.
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
_M_insert_dispatch(__position, __first, __last, _Integral());
}
#endif
#if __cplusplus >= 201103L
_GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __position, size_type __n, const bool& __x)
{
difference_type __offset = __position - cbegin();
_M_fill_insert(__position._M_const_cast(), __n, __x);
return begin() + __offset;
}
#else
void
insert(iterator __position, size_type __n, const bool& __x)
{ _M_fill_insert(__position, __n, __x); }
#endif
#if __cplusplus >= 201103L
_GLIBCXX20_CONSTEXPR
iterator
insert(const_iterator __p, initializer_list<bool> __l)
{ return this->insert(__p, __l.begin(), __l.end()); }
#endif
#if __glibcxx_containers_ranges // C++ >= 23
/**
* @brief Insert a range into the vector.
* @param __rg A range of values that are convertible to `bool`.
* @return An iterator that points to the first new element inserted,
* or to `__pos` if `__rg` is an empty range.
* @pre `__rg` and `*this` do not overlap.
* @since C++23
*/
template<__detail::__container_compatible_range<bool> _Rg>
constexpr iterator
insert_range(const_iterator __pos, _Rg&& __rg)
{
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
{
if (auto __n = size_type(ranges::distance(__rg)))
{
if (capacity() - size() >= __n)
{
std::copy_backward(__pos._M_const_cast(), end(),
this->_M_impl._M_finish
+ difference_type(__n));
ranges::copy(__rg, __pos._M_const_cast());
this->_M_impl._M_finish += difference_type(__n);
return __pos._M_const_cast();
}
else
{
const size_type __len =
_M_check_len(__n, "vector<bool>::insert_range");
const iterator __begin = begin(), __end = end();
_Bit_pointer __q = this->_M_allocate(__len);
iterator __start(std::__addressof(*__q), 0);
iterator __i = _M_copy_aligned(__begin,
__pos._M_const_cast(),
__start);
iterator __j = ranges::copy(__rg, __i).out;
iterator __finish = std::copy(__pos._M_const_cast(),
__end, __j);
this->_M_deallocate();
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
this->_M_impl._M_start = __start;
this->_M_impl._M_finish = __finish;
return __i;
}
}
else
return __pos._M_const_cast();
}
else
return insert_range(__pos,
vector(from_range, __rg, get_allocator()));
}
/**
* @brief Append a range at the end of the vector.
* @since C++23
*/
template<__detail::__container_compatible_range<bool> _Rg>
constexpr void
append_range(_Rg&& __rg)
{
// N.B. __rg may overlap with *this, so we must copy from __rg before
// existing elements or iterators referring to *this are invalidated.
// e.g. in v.append_range(views::concat(v, foo)) rg overlaps v.
if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
{
const auto __n = size_type(ranges::distance(__rg));
// If there is no existing storage, there are no iterators that
// can be referring to our storage, so it's safe to allocate now.
if (capacity() == 0)
reserve(__n);
const auto __sz = size();
const auto __capacity = capacity();
if ((__capacity - __sz) >= __n)
{
this->_M_impl._M_finish
= ranges::copy(std::forward<_Rg>(__rg), end()).out;
return;
}
vector __tmp(get_allocator());
__tmp.reserve(_M_check_len(__n, "vector::append_range"));
__tmp._M_impl._M_finish
= _M_copy_aligned(cbegin(), cend(), __tmp.begin());
__tmp._M_impl._M_finish
= ranges::copy(std::forward<_Rg>(__rg), __tmp.end()).out;
swap(__tmp);
}
else
{
auto __first = ranges::begin(__rg);
const auto __last = ranges::end(__rg);
// Fill up to the end of current capacity.
for (auto __free = capacity() - size();
__first != __last && __free > 0;
++__first, (void) --__free)
emplace_back(*__first);
if (__first == __last)
return;
// Copy the rest of the range to a new vector.
ranges::subrange __rest(std::move(__first), __last);
vector __tmp(from_range, __rest, get_allocator());
insert(end(), __tmp.begin(), __tmp.end());
}
}
#endif // containers_ranges
_GLIBCXX20_CONSTEXPR
void
pop_back()
{ --this->_M_impl._M_finish; }
_GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __position)
#else
erase(iterator __position)
#endif
{ return _M_erase(__position._M_const_cast()); }
_GLIBCXX20_CONSTEXPR
iterator
#if __cplusplus >= 201103L
erase(const_iterator __first, const_iterator __last)
#else
erase(iterator __first, iterator __last)
#endif
{ return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
_GLIBCXX20_CONSTEXPR
void
resize(size_type __new_size, bool __x = bool())
{
if (__new_size < size())
_M_erase_at_end(begin() + difference_type(__new_size));
else
insert(end(), __new_size - size(), __x);
}
#if __cplusplus >= 201103L
_GLIBCXX20_CONSTEXPR
void
shrink_to_fit()
{ _M_shrink_to_fit(); }
#endif
_GLIBCXX20_CONSTEXPR
void
flip() _GLIBCXX_NOEXCEPT
{
_Bit_type * const __end = this->_M_impl._M_end_addr();
for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p)
*__p = ~*__p;
}
_GLIBCXX20_CONSTEXPR
void
clear() _GLIBCXX_NOEXCEPT
{ _M_erase_at_end(begin()); }
#if __cplusplus >= 201103L
template<typename... _Args>
#if __cplusplus > 201402L
_GLIBCXX20_CONSTEXPR
reference
#else
void
#endif
emplace_back(_Args&&... __args)
{
push_back(bool(std::forward<_Args>(__args)...));
#if __cplusplus > 201402L
return back();
#endif
}
template<typename... _Args>
_GLIBCXX20_CONSTEXPR
iterator
emplace(const_iterator __pos, _Args&&... __args)
{ return insert(__pos, bool(std::forward<_Args>(__args)...)); }
#endif
protected:
// Precondition: __first._M_offset == 0 && __result._M_offset == 0.
_GLIBCXX20_CONSTEXPR
iterator
_M_copy_aligned(const_iterator __first, const_iterator __last,
iterator __result)
{
_Bit_type* __q = std::copy(__first._M_p, __last._M_p, __result._M_p);
return std::copy(const_iterator(__last._M_p, 0), __last,
iterator(__q, 0));
}
_GLIBCXX20_CONSTEXPR
void
_M_initialize(size_type __n)
{
if (__n)
{
_Bit_pointer __q = this->_M_allocate(__n);
this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
iterator __start = iterator(std::__addressof(*__q), 0);
this->_M_impl._M_start = __start;
this->_M_impl._M_finish = __start + difference_type(__n);
}
}
_GLIBCXX20_CONSTEXPR
void
_M_initialize_value(bool __x) _GLIBCXX_NOEXCEPT
{
if (_Bit_type* __p = this->_M_impl._M_start._M_p)
__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
#if __cplusplus < 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
void
_M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
{
_M_initialize(static_cast<size_type>(__n));
_M_initialize_value(__x);
}
template<typename _InputIterator>
void
_M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
__false_type)
{ _M_initialize_range(__first, __last,
std::__iterator_category(__first)); }
#endif
template<typename _InputIterator>
_GLIBCXX20_CONSTEXPR
void
_M_initialize_range(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
{
for (; __first != __last; ++__first)
push_back(*__first);
}
template<typename _ForwardIterator>
_GLIBCXX20_CONSTEXPR
void
_M_initialize_range(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag)
{
const size_type __n = std::distance(__first, __last);
_M_initialize(__n);
std::copy(__first, __last, begin());
}
#if __cplusplus < 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
void
_M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
{ _M_fill_assign(__n, __val); }
template<class _InputIterator>
void
_M_assign_dispatch(_InputIterator __first, _InputIterator __last,
__false_type)
{ _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
#endif
_GLIBCXX20_CONSTEXPR
void
_M_fill_assign(size_t __n, bool __x)
{
if (__n > size())
{
_M_initialize_value(__x);
insert(end(), __n - size(), __x);
}
else
{
_M_erase_at_end(begin() + __n);
_M_initialize_value(__x);
}
}
template<typename _InputIterator>
_GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
{
iterator __cur = begin();
for (; __first != __last && __cur != end(); ++__cur, (void)++__first)
*__cur = *__first;
if (__first == __last)
_M_erase_at_end(__cur);
else
insert(end(), __first, __last);
}
template<typename _ForwardIterator>
_GLIBCXX20_CONSTEXPR
void
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
std::forward_iterator_tag)
{
const size_type __len = std::distance(__first, __last);
if (__len < size())
_M_erase_at_end(std::copy(__first, __last, begin()));
else
{
_ForwardIterator __mid = __first;
std::advance(__mid, size());
std::copy(__first, __mid, begin());
insert(end(), __mid, __last);
}
}
#if __cplusplus < 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
void
_M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x,
__true_type)
{ _M_fill_insert(__pos, __n, __x); }
template<typename _InputIterator>
void
_M_insert_dispatch(iterator __pos,
_InputIterator __first, _InputIterator __last,
__false_type)
{ _M_insert_range(__pos, __first, __last,
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)
{
for (; __first != __last; ++__first)
{
__pos = insert(__pos, *__first);
++__pos;
}
}
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
{
if (max_size() - size() < __n)
__throw_length_error(__N(__s));
const size_type __len = size() + std::max(size(), __n);
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);
protected:
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 464. Suggestion for new member functions in standard containers.
// N.B. DR 464 says nothing about vector<bool> but we need something
// here due to the using-declaration in __gnu_debug::vector.
// vector class.
#if __cplusplus >= 201103L
void data() = delete;
#else
void data() { }
#endif
};
_GLIBCXX_END_NAMESPACE_CONTAINER
// Fill a partial word.
_GLIBCXX20_CONSTEXPR
inline void
__fill_bvector(_Bit_type* __v, unsigned int __first, unsigned int __last,
bool __x) _GLIBCXX_NOEXCEPT
{
const _Bit_type __fmask = ~0ul << __first;
const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last);
const _Bit_type __mask = __fmask & __lmask;
if (__x)
*__v |= __mask;
else
*__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 __cpp_lib_is_constant_evaluated
if (std::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)
{
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);
__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);
}
else if (__first._M_offset != __last._M_offset)
__fill_bvector(__first._M_p, __first._M_offset, __last._M_offset, __x);
}
#if __cplusplus >= 201103L
// DR 1182.
/// std::hash specialization for vector<bool>.
template<typename _Alloc>
struct hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>
: public __hash_base<size_t, _GLIBCXX_STD_C::vector<bool, _Alloc>>
{
size_t
operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>&) const noexcept;
};
#endif // C++11
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif