2010-05-11 19:42:16 +00:00
|
|
|
// -*- C++ -*-
|
2021-11-17 16:25:01 -05:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
2019-01-19 10:56:40 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_VECTOR
|
|
|
|
#define _LIBCPP_VECTOR
|
|
|
|
|
2023-12-04 15:17:31 -05:00
|
|
|
// clang-format off
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
/*
|
|
|
|
vector synopsis
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, class Allocator = allocator<T> >
|
2010-05-11 19:42:16 +00:00
|
|
|
class vector
|
2010-08-22 00:02:43 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef T value_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef Allocator allocator_type;
|
|
|
|
typedef typename allocator_type::reference reference;
|
|
|
|
typedef typename allocator_type::const_reference const_reference;
|
|
|
|
typedef implementation-defined iterator;
|
|
|
|
typedef implementation-defined const_iterator;
|
|
|
|
typedef typename allocator_type::size_type size_type;
|
|
|
|
typedef typename allocator_type::difference_type difference_type;
|
|
|
|
typedef typename allocator_type::pointer pointer;
|
|
|
|
typedef typename allocator_type::const_pointer const_pointer;
|
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
vector()
|
|
|
|
noexcept(is_nothrow_default_constructible<allocator_type>::value);
|
|
|
|
explicit vector(const allocator_type&);
|
2010-05-11 19:42:16 +00:00
|
|
|
explicit vector(size_type n);
|
2013-09-14 00:47:59 +00:00
|
|
|
explicit vector(size_type n, const allocator_type&); // C++14
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(size_type n, const value_type& value, const allocator_type& = allocator_type());
|
|
|
|
template <class InputIterator>
|
|
|
|
vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type());
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(const vector& x);
|
2011-06-03 19:40:40 +00:00
|
|
|
vector(vector&& x)
|
|
|
|
noexcept(is_nothrow_move_constructible<allocator_type>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(initializer_list<value_type> il);
|
|
|
|
vector(initializer_list<value_type> il, const allocator_type& a);
|
|
|
|
~vector();
|
|
|
|
vector& operator=(const vector& x);
|
2011-06-03 19:40:40 +00:00
|
|
|
vector& operator=(vector&& x)
|
|
|
|
noexcept(
|
2015-08-18 18:57:00 +00:00
|
|
|
allocator_type::propagate_on_container_move_assignment::value ||
|
|
|
|
allocator_type::is_always_equal::value); // C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
vector& operator=(initializer_list<value_type> il);
|
|
|
|
template <class InputIterator>
|
|
|
|
void assign(InputIterator first, InputIterator last);
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr void assign_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void assign(size_type n, const value_type& u);
|
|
|
|
void assign(initializer_list<value_type> il);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
allocator_type get_allocator() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
iterator begin() noexcept;
|
|
|
|
const_iterator begin() const noexcept;
|
|
|
|
iterator end() noexcept;
|
|
|
|
const_iterator end() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
reverse_iterator rbegin() noexcept;
|
|
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
|
|
reverse_iterator rend() noexcept;
|
|
|
|
const_reverse_iterator rend() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
const_iterator cbegin() const noexcept;
|
|
|
|
const_iterator cend() const noexcept;
|
|
|
|
const_reverse_iterator crbegin() const noexcept;
|
|
|
|
const_reverse_iterator crend() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
size_type size() const noexcept;
|
|
|
|
size_type max_size() const noexcept;
|
|
|
|
size_type capacity() const noexcept;
|
|
|
|
bool empty() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
void reserve(size_type n);
|
2011-06-03 19:40:40 +00:00
|
|
|
void shrink_to_fit() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
reference operator[](size_type n);
|
|
|
|
const_reference operator[](size_type n) const;
|
|
|
|
reference at(size_type n);
|
|
|
|
const_reference at(size_type n) const;
|
|
|
|
|
|
|
|
reference front();
|
|
|
|
const_reference front() const;
|
|
|
|
reference back();
|
|
|
|
const_reference back() const;
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
value_type* data() noexcept;
|
|
|
|
const value_type* data() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
void push_back(const value_type& x);
|
|
|
|
void push_back(value_type&& x);
|
|
|
|
template <class... Args>
|
2017-01-24 23:09:12 +00:00
|
|
|
reference emplace_back(Args&&... args); // reference in C++17
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr void append_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void pop_back();
|
|
|
|
|
|
|
|
template <class... Args> iterator emplace(const_iterator position, Args&&... args);
|
|
|
|
iterator insert(const_iterator position, const value_type& x);
|
|
|
|
iterator insert(const_iterator position, value_type&& x);
|
|
|
|
iterator insert(const_iterator position, size_type n, const value_type& x);
|
|
|
|
template <class InputIterator>
|
|
|
|
iterator insert(const_iterator position, InputIterator first, InputIterator last);
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr iterator insert_range(const_iterator position, R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator insert(const_iterator position, initializer_list<value_type> il);
|
|
|
|
|
|
|
|
iterator erase(const_iterator position);
|
|
|
|
iterator erase(const_iterator first, const_iterator last);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
void clear() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
void resize(size_type sz);
|
|
|
|
void resize(size_type sz, const value_type& c);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
void swap(vector&)
|
2015-07-13 20:04:56 +00:00
|
|
|
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
|
|
|
|
allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
bool __invariants() const;
|
2010-08-22 00:02:43 +00:00
|
|
|
};
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class Allocator = allocator<T> >
|
2010-05-11 19:42:16 +00:00
|
|
|
class vector<bool, Allocator>
|
2010-08-22 00:02:43 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef bool value_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef Allocator allocator_type;
|
|
|
|
typedef implementation-defined iterator;
|
|
|
|
typedef implementation-defined const_iterator;
|
|
|
|
typedef typename allocator_type::size_type size_type;
|
|
|
|
typedef typename allocator_type::difference_type difference_type;
|
|
|
|
typedef iterator pointer;
|
|
|
|
typedef const_iterator const_pointer;
|
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
|
|
|
|
|
|
class reference
|
|
|
|
{
|
|
|
|
public:
|
2011-06-03 19:40:40 +00:00
|
|
|
reference(const reference&) noexcept;
|
|
|
|
operator bool() const noexcept;
|
2021-06-29 13:52:26 -04:00
|
|
|
reference& operator=(bool x) noexcept;
|
2011-06-03 19:40:40 +00:00
|
|
|
reference& operator=(const reference& x) noexcept;
|
|
|
|
iterator operator&() const noexcept;
|
|
|
|
void flip() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class const_reference
|
|
|
|
{
|
|
|
|
public:
|
2011-06-03 19:40:40 +00:00
|
|
|
const_reference(const reference&) noexcept;
|
|
|
|
operator bool() const noexcept;
|
|
|
|
const_iterator operator&() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
vector()
|
|
|
|
noexcept(is_nothrow_default_constructible<allocator_type>::value);
|
2011-09-02 20:42:31 +00:00
|
|
|
explicit vector(const allocator_type&);
|
2013-09-14 00:47:59 +00:00
|
|
|
explicit vector(size_type n, const allocator_type& a = allocator_type()); // C++14
|
|
|
|
vector(size_type n, const value_type& value, const allocator_type& = allocator_type());
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class InputIterator>
|
|
|
|
vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type());
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<bool> R>
|
|
|
|
constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(const vector& x);
|
2011-06-03 19:40:40 +00:00
|
|
|
vector(vector&& x)
|
|
|
|
noexcept(is_nothrow_move_constructible<allocator_type>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(initializer_list<value_type> il);
|
|
|
|
vector(initializer_list<value_type> il, const allocator_type& a);
|
|
|
|
~vector();
|
|
|
|
vector& operator=(const vector& x);
|
2011-06-03 19:40:40 +00:00
|
|
|
vector& operator=(vector&& x)
|
|
|
|
noexcept(
|
2015-08-18 18:57:00 +00:00
|
|
|
allocator_type::propagate_on_container_move_assignment::value ||
|
|
|
|
allocator_type::is_always_equal::value); // C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
vector& operator=(initializer_list<value_type> il);
|
|
|
|
template <class InputIterator>
|
|
|
|
void assign(InputIterator first, InputIterator last);
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr void assign_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void assign(size_type n, const value_type& u);
|
|
|
|
void assign(initializer_list<value_type> il);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
allocator_type get_allocator() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
iterator begin() noexcept;
|
|
|
|
const_iterator begin() const noexcept;
|
|
|
|
iterator end() noexcept;
|
|
|
|
const_iterator end() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
reverse_iterator rbegin() noexcept;
|
|
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
|
|
reverse_iterator rend() noexcept;
|
|
|
|
const_reverse_iterator rend() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
const_iterator cbegin() const noexcept;
|
|
|
|
const_iterator cend() const noexcept;
|
|
|
|
const_reverse_iterator crbegin() const noexcept;
|
|
|
|
const_reverse_iterator crend() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
size_type size() const noexcept;
|
|
|
|
size_type max_size() const noexcept;
|
|
|
|
size_type capacity() const noexcept;
|
|
|
|
bool empty() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
void reserve(size_type n);
|
2011-06-03 19:40:40 +00:00
|
|
|
void shrink_to_fit() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
reference operator[](size_type n);
|
|
|
|
const_reference operator[](size_type n) const;
|
|
|
|
reference at(size_type n);
|
|
|
|
const_reference at(size_type n) const;
|
|
|
|
|
|
|
|
reference front();
|
|
|
|
const_reference front() const;
|
|
|
|
reference back();
|
|
|
|
const_reference back() const;
|
|
|
|
|
|
|
|
void push_back(const value_type& x);
|
2017-01-24 23:09:12 +00:00
|
|
|
template <class... Args> reference emplace_back(Args&&... args); // C++14; reference in C++17
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr void append_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void pop_back();
|
|
|
|
|
2013-08-13 23:54:12 +00:00
|
|
|
template <class... Args> iterator emplace(const_iterator position, Args&&... args); // C++14
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator insert(const_iterator position, const value_type& x);
|
|
|
|
iterator insert(const_iterator position, size_type n, const value_type& x);
|
|
|
|
template <class InputIterator>
|
|
|
|
iterator insert(const_iterator position, InputIterator first, InputIterator last);
|
2023-05-08 23:40:21 -07:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
constexpr iterator insert_range(const_iterator position, R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator insert(const_iterator position, initializer_list<value_type> il);
|
|
|
|
|
|
|
|
iterator erase(const_iterator position);
|
|
|
|
iterator erase(const_iterator first, const_iterator last);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
void clear() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
void resize(size_type sz);
|
|
|
|
void resize(size_type sz, value_type x);
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
void swap(vector&)
|
2015-07-13 20:04:56 +00:00
|
|
|
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
|
|
|
|
allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
2011-06-03 19:40:40 +00:00
|
|
|
void flip() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
bool __invariants() const;
|
2010-08-22 00:02:43 +00:00
|
|
|
};
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2018-05-21 21:30:12 +00:00
|
|
|
template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
|
|
|
|
vector(InputIterator, InputIterator, Allocator = Allocator())
|
2021-11-09 09:21:02 -08:00
|
|
|
-> vector<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17
|
2018-05-21 21:30:12 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>>
|
|
|
|
vector(from_range_t, R&&, Allocator = Allocator())
|
|
|
|
-> vector<ranges::range_value_t<R>, Allocator>; // C++23
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class Allocator> struct hash<std::vector<bool, Allocator>>;
|
|
|
|
|
2023-05-20 18:37:00 +03:00
|
|
|
template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // constexpr since C++20
|
|
|
|
template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20
|
|
|
|
template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20
|
|
|
|
template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20
|
|
|
|
template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20
|
|
|
|
template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20
|
|
|
|
template <class T, class Allocator> constexpr
|
|
|
|
constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x,
|
|
|
|
const vector<T, Allocator>& y); // since C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
template <class T, class Allocator>
|
|
|
|
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
|
|
|
|
noexcept(noexcept(x.swap(y)));
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class T, class Allocator, class U>
|
2020-05-02 13:58:03 +02:00
|
|
|
typename vector<T, Allocator>::size_type
|
2023-05-20 18:37:00 +03:00
|
|
|
erase(vector<T, Allocator>& c, const U& value); // since C++20
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class T, class Allocator, class Predicate>
|
2020-05-02 13:58:03 +02:00
|
|
|
typename vector<T, Allocator>::size_type
|
2023-05-20 18:37:00 +03:00
|
|
|
erase_if(vector<T, Allocator>& c, Predicate pred); // since C++20
|
2018-12-14 18:49:35 +00:00
|
|
|
|
2022-11-29 07:57:30 +01:00
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool is-vector-bool-reference = see below; // exposition only, since C++23
|
|
|
|
|
|
|
|
template<class T, class charT> requires is-vector-bool-reference<T> // Since C++23
|
|
|
|
struct formatter<T, charT>;
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
} // std
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2023-12-04 15:17:31 -05:00
|
|
|
// clang-format on
|
|
|
|
|
2022-02-15 18:18:08 +01:00
|
|
|
#include <__algorithm/copy.h>
|
|
|
|
#include <__algorithm/equal.h>
|
|
|
|
#include <__algorithm/fill_n.h>
|
2023-05-08 23:40:21 -07:00
|
|
|
#include <__algorithm/iterator_operations.h>
|
2022-02-15 18:18:08 +01:00
|
|
|
#include <__algorithm/lexicographical_compare.h>
|
2023-05-20 18:37:00 +03:00
|
|
|
#include <__algorithm/lexicographical_compare_three_way.h>
|
2022-02-15 18:18:08 +01:00
|
|
|
#include <__algorithm/remove.h>
|
|
|
|
#include <__algorithm/remove_if.h>
|
|
|
|
#include <__algorithm/rotate.h>
|
|
|
|
#include <__algorithm/unwrap_iter.h>
|
2022-03-25 12:55:36 -04:00
|
|
|
#include <__assert> // all public C++ headers provide the assertion handler
|
2023-03-29 16:48:20 -04:00
|
|
|
#include <__availability>
|
2010-05-11 19:42:16 +00:00
|
|
|
#include <__bit_reference>
|
2022-11-29 07:57:30 +01:00
|
|
|
#include <__concepts/same_as.h>
|
2022-01-07 09:45:05 -05:00
|
|
|
#include <__config>
|
2021-09-26 15:47:42 +02:00
|
|
|
#include <__format/enable_insertable.h>
|
2022-11-29 07:57:30 +01:00
|
|
|
#include <__format/formatter.h>
|
2023-04-20 20:53:46 +02:00
|
|
|
#include <__format/formatter_bool.h>
|
2022-02-15 18:18:08 +01:00
|
|
|
#include <__functional/hash.h>
|
2022-05-21 00:45:51 +02:00
|
|
|
#include <__functional/unary_function.h>
|
2022-06-10 19:53:10 +02:00
|
|
|
#include <__iterator/advance.h>
|
2023-05-08 23:40:21 -07:00
|
|
|
#include <__iterator/distance.h>
|
2021-11-09 09:21:02 -08:00
|
|
|
#include <__iterator/iterator_traits.h>
|
2022-06-10 19:53:10 +02:00
|
|
|
#include <__iterator/reverse_iterator.h>
|
2021-06-11 09:55:11 -04:00
|
|
|
#include <__iterator/wrap_iter.h>
|
2023-03-01 20:13:55 +01:00
|
|
|
#include <__memory/addressof.h>
|
2022-04-09 09:41:19 +02:00
|
|
|
#include <__memory/allocate_at_least.h>
|
[ASan][libcxx] Annotating std::vector with all allocators
This revision is a part of a series of patches extending
AddressSanitizer C++ container overflow detection
capabilities by adding annotations, similar to those existing
in std::vector, to std::string and std::deque collections.
These changes allow ASan to detect cases when the instrumented
program accesses memory which is internally allocated by
the collection but is still not in-use (accesses before or
after the stored elements for std::deque, or between the size and
capacity bounds for std::string).
The motivation for the research and those changes was a bug,
found by Trail of Bits, in a real code where an out-of-bounds read
could happen as two strings were compared via a std::equals function
that took iter1_begin, iter1_end, iter2_begin iterators
(with a custom comparison function).
When object iter1 was longer than iter2, read out-of-bounds on iter2
could happen. Container sanitization would detect it.
In revision D132522, support for non-aligned memory buffers (sharing
first/last granule with other objects) was added, therefore the
check for standard allocator is not necessary anymore.
This patch removes the check in std::vector annotation member
function (__annotate_contiguous_container) to support
different allocators.
Additionally, this revision fixes unpoisoning in std::vector.
It guarantees that __alloc_traits::deallocate may access returned memory.
Originally suggested in D144155 revision.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
Reviewed By: #libc, #sanitizers, philnik, vitalybuka, ldionne
Spies: mikhail.ramalho, manojgupta, ldionne, AntonBikineev, ayzhao, hans, EricWF, philnik, #sanitizers, libcxx-commits
Differential Revision: https://reviews.llvm.org/D136765
2023-05-04 17:43:51 -07:00
|
|
|
#include <__memory/allocator_traits.h>
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
#include <__memory/pointer_traits.h>
|
|
|
|
#include <__memory/swap_allocator.h>
|
2022-09-05 00:01:15 +02:00
|
|
|
#include <__memory/temp_value.h>
|
|
|
|
#include <__memory/uninitialized_algorithms.h>
|
2022-10-06 16:53:30 -04:00
|
|
|
#include <__memory_resource/polymorphic_allocator.h>
|
2023-05-08 23:40:21 -07:00
|
|
|
#include <__ranges/access.h>
|
|
|
|
#include <__ranges/concepts.h>
|
|
|
|
#include <__ranges/container_compatible_range.h>
|
|
|
|
#include <__ranges/from_range.h>
|
|
|
|
#include <__ranges/size.h>
|
2021-05-19 11:57:04 -04:00
|
|
|
#include <__split_buffer>
|
2022-09-05 00:01:15 +02:00
|
|
|
#include <__type_traits/is_allocator.h>
|
2023-02-12 12:32:36 +01:00
|
|
|
#include <__type_traits/is_constructible.h>
|
|
|
|
#include <__type_traits/is_nothrow_move_assignable.h>
|
2022-09-05 00:01:15 +02:00
|
|
|
#include <__type_traits/noexcept_move_assign_container.h>
|
2023-02-12 12:32:36 +01:00
|
|
|
#include <__type_traits/type_identity.h>
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
#include <__utility/exception_guard.h>
|
2021-06-05 02:47:47 +00:00
|
|
|
#include <__utility/forward.h>
|
2022-03-05 19:17:07 +01:00
|
|
|
#include <__utility/move.h>
|
2023-05-08 23:40:21 -07:00
|
|
|
#include <__utility/pair.h>
|
2022-03-05 19:17:07 +01:00
|
|
|
#include <__utility/swap.h>
|
2010-05-11 19:42:16 +00:00
|
|
|
#include <climits>
|
2021-05-19 11:57:04 -04:00
|
|
|
#include <cstring>
|
|
|
|
#include <iosfwd> // for forward declaration of vector
|
|
|
|
#include <limits>
|
2010-05-11 19:42:16 +00:00
|
|
|
#include <stdexcept>
|
2018-09-12 19:41:40 +00:00
|
|
|
#include <version>
|
Ok, 3 major changes for debug mode in one commit:
1. I had been detecting and trapping iterator == and \!= among iterators
in different containers as an error. But the trapping itself is actually
an error.
Consider:
#include <iostream>
#include <vector>
#include <algorithm>
template <class C>
void
display(const C& c)
{
std::cout << "{";
bool first = true;
for (const auto& x : c)
{
if (\!first)
std::cout << ", ";
first = false;
std::cout << x;
}
std::cout << "}\n";
}
int
main()
{
typedef std::vector<int> V;
V v1 = {1, 3, 5};
V v2 = {2, 4, 6};
display(v1);
display(v2);
V::iterator i = std::find(v1.begin(), v1.end(), 1);
V::iterator j = std::find(v2.begin(), v2.end(), 2);
if (*i == *j)
i = j; // perfectly legal
// ...
if (i \!= j) // the only way to check
v2.push_back(*i);
display(v1);
display(v2);
}
It is legal to assign an iterator from one container to another of the
same type. This is required to work. One might want to test whether or
not such an assignment had been made. The way one performs such a check
is using the iterator's ==, \!= operator. This is a logical and necessary
function and does not constitute an error.
2. I had a header circular dependence bug when _LIBCPP_DEBUG2 is defined.
This caused a problem in several of the libc++ tests.
Fixed.
3. There is a serious problem when _LIBCPP_DEBUG2=1 at the moment in that
std::basic_string is inoperable. std::basic_string uses __wrap_iterator
to implement its iterators. __wrap_iterator has been rigged up in debug
mode to support vector. But string hasn't been rigged up yet. This means
that one gets false positives when using std::string in debug mode. I've
upped std::string's priority in www/debug_mode.html.
llvm-svn: 187636
2013-08-02 00:26:35 +00:00
|
|
|
|
2022-06-16 22:43:46 +02:00
|
|
|
// standard-mandated includes
|
|
|
|
|
|
|
|
// [iterator.range]
|
|
|
|
#include <__iterator/access.h>
|
|
|
|
#include <__iterator/data.h>
|
|
|
|
#include <__iterator/empty.h>
|
|
|
|
#include <__iterator/reverse_access.h>
|
|
|
|
#include <__iterator/size.h>
|
|
|
|
|
|
|
|
// [vector.syn]
|
|
|
|
#include <compare>
|
|
|
|
#include <initializer_list>
|
|
|
|
|
2011-10-17 20:05:10 +00:00
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
2022-02-01 20:16:40 -05:00
|
|
|
# pragma GCC system_header
|
2011-10-17 20:05:10 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2017-05-31 22:07:49 +00:00
|
|
|
_LIBCPP_PUSH_MACROS
|
|
|
|
#include <__undef_macros>
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
2016-02-20 00:19:45 +00:00
|
|
|
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
|
2017-01-04 23:56:00 +00:00
|
|
|
class _LIBCPP_TEMPLATE_VIS vector {
|
2010-05-11 19:42:16 +00:00
|
|
|
private:
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
typedef allocator<_Tp> __default_allocator_type;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
public:
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
typedef vector __self;
|
|
|
|
typedef _Tp value_type;
|
|
|
|
typedef _Allocator allocator_type;
|
|
|
|
typedef allocator_traits<allocator_type> __alloc_traits;
|
|
|
|
typedef value_type& reference;
|
|
|
|
typedef const value_type& const_reference;
|
|
|
|
typedef typename __alloc_traits::size_type size_type;
|
|
|
|
typedef typename __alloc_traits::difference_type difference_type;
|
|
|
|
typedef typename __alloc_traits::pointer pointer;
|
|
|
|
typedef typename __alloc_traits::const_pointer const_pointer;
|
2022-11-14 10:33:03 -10:00
|
|
|
// TODO: Implement iterator bounds checking without requiring the global database.
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
typedef __wrap_iter<pointer> iterator;
|
|
|
|
typedef __wrap_iter<const_pointer> const_iterator;
|
2022-07-31 17:53:10 +02:00
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2013-03-26 19:04:56 +00:00
|
|
|
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
|
|
|
"Allocator::value_type must be same type as value_type");
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-10-08 22:17:32 +02:00
|
|
|
static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
|
|
|
|
"[allocator.requirements] states that rebinding an allocator to the same type should result in the "
|
|
|
|
"original allocator");
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector()
|
2015-06-04 02:05:41 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) {}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a)
|
2015-06-04 00:10:20 +00:00
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
|
|
|
|
#else
|
|
|
|
_NOEXCEPT
|
|
|
|
#endif
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
2011-09-14 18:33:51 +00:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n);
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a);
|
2013-09-14 00:47:59 +00:00
|
|
|
#endif
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x);
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
|
|
|
|
template <class = __enable_if_t<__is_allocator<_Allocator>::value> >
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
vector(size_type __n, const value_type& __x, const allocator_type& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
if (__n > 0) {
|
|
|
|
__vallocate(__n);
|
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 11:55:46 -08:00
|
|
|
|
2022-08-15 14:09:49 +02:00
|
|
|
template <class _InputIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _InputIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
|
|
|
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
|
|
|
|
|
|
|
|
template <
|
|
|
|
class _ForwardIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
|
|
|
|
template <
|
|
|
|
class _ForwardIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
|
|
|
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr vector(
|
|
|
|
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
|
|
|
|
: __end_cap_(nullptr, __alloc) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
__init_with_sentinel(ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-11-17 21:34:29 +01:00
|
|
|
private:
|
|
|
|
class __destroy_vector {
|
|
|
|
public:
|
2023-05-29 14:24:15 -07:00
|
|
|
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-11-17 21:34:29 +01:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
|
|
|
|
if (__vec_.__begin_ != nullptr) {
|
|
|
|
__vec_.__clear();
|
[ASan][libcxx] Annotating std::vector with all allocators
This revision is a part of a series of patches extending
AddressSanitizer C++ container overflow detection
capabilities by adding annotations, similar to those existing
in std::vector, to std::string and std::deque collections.
These changes allow ASan to detect cases when the instrumented
program accesses memory which is internally allocated by
the collection but is still not in-use (accesses before or
after the stored elements for std::deque, or between the size and
capacity bounds for std::string).
The motivation for the research and those changes was a bug,
found by Trail of Bits, in a real code where an out-of-bounds read
could happen as two strings were compared via a std::equals function
that took iter1_begin, iter1_end, iter2_begin iterators
(with a custom comparison function).
When object iter1 was longer than iter2, read out-of-bounds on iter2
could happen. Container sanitization would detect it.
In revision D132522, support for non-aligned memory buffers (sharing
first/last granule with other objects) was added, therefore the
check for standard allocator is not necessary anymore.
This patch removes the check in std::vector annotation member
function (__annotate_contiguous_container) to support
different allocators.
Additionally, this revision fixes unpoisoning in std::vector.
It guarantees that __alloc_traits::deallocate may access returned memory.
Originally suggested in D144155 revision.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
Reviewed By: #libc, #sanitizers, philnik, vitalybuka, ldionne
Spies: mikhail.ramalho, manojgupta, ldionne, AntonBikineev, ayzhao, hans, EricWF, philnik, #sanitizers, libcxx-commits
Differential Revision: https://reviews.llvm.org/D136765
2023-05-04 17:43:51 -07:00
|
|
|
__vec_.__annotate_delete();
|
2022-11-17 21:34:29 +01:00
|
|
|
__alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity());
|
2021-11-08 00:10:13 -08:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
vector& __vec_;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
|
|
|
vector(const vector& __x, const __type_identity_t<allocator_type>& __a);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(initializer_list<value_type> __il);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
2017-04-16 02:40:45 +00:00
|
|
|
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
|
|
|
|
2022-05-19 12:46:09 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(initializer_list<value_type> __il) {
|
|
|
|
assign(__il.begin(), __il.end());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(vector&& __x)
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2022-05-19 12:46:09 +02:00
|
|
|
noexcept;
|
2015-07-14 14:46:32 +00:00
|
|
|
#else
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
2015-07-14 14:46:32 +00:00
|
|
|
#endif
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
2022-03-18 17:49:02 +01:00
|
|
|
vector(vector&& __x, const __type_identity_t<allocator_type>& __a);
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(vector&& __x)
|
2024-01-30 08:33:48 -05:00
|
|
|
_NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-15 14:09:49 +02:00
|
|
|
template <class _InputIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last);
|
|
|
|
template <
|
|
|
|
class _ForwardIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_ForwardIterator __first, _ForwardIterator __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void assign_range(_Range&& __range) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
__assign_with_size(ranges::begin(__range), ranges::end(__range), __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
} else {
|
|
|
|
__assign_with_sentinel(ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const_reference __u);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(initializer_list<value_type> __il) {
|
2010-05-11 19:42:16 +00:00
|
|
|
assign(__il.begin(), __il.end());
|
|
|
|
}
|
2017-04-16 02:40:45 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return this->__alloc();
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return reverse_iterator(end());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT {
|
|
|
|
return const_reverse_iterator(end());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT {
|
|
|
|
return reverse_iterator(begin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT {
|
|
|
|
return const_reverse_iterator(begin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT {
|
2011-09-14 18:33:51 +00:00
|
|
|
return rbegin();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return static_cast<size_type>(this->__end_ - this->__begin_);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
return static_cast<size_type>(__end_cap() - this->__begin_);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return this->__begin_ == this->__end_;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
|
2011-09-14 18:33:51 +00:00
|
|
|
return *this->__begin_;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
|
2011-09-14 18:33:51 +00:00
|
|
|
return *this->__begin_;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
|
2011-09-14 18:33:51 +00:00
|
|
|
return *(this->__end_ - 1);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
|
2011-09-14 18:33:51 +00:00
|
|
|
return *(this->__end_ - 1);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::__to_address(this->__begin_);
|
|
|
|
}
|
[libc++] Implement P1004R2 (constexpr std::vector)
Reviewed By: #libc, ldionne
Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits
Differential Revision: https://reviews.llvm.org/D68365
2022-07-27 14:41:40 +02:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::__to_address(this->__begin_);
|
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2016-07-21 03:20:17 +00:00
|
|
|
reference
|
|
|
|
emplace_back(_Args&&... __args);
|
2017-01-24 23:09:12 +00:00
|
|
|
#else
|
|
|
|
void
|
|
|
|
emplace_back(_Args&&... __args);
|
|
|
|
#endif
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
|
|
|
|
insert_range(end(), std::forward<_Range>(__range));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back();
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, value_type&& __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __position, _Args&&... __args);
|
2022-08-17 11:17:34 +02:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
2022-08-17 11:17:34 +02:00
|
|
|
insert(const_iterator __position, size_type __n, const_reference __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2022-08-15 14:09:49 +02:00
|
|
|
template <class _InputIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
|
|
|
insert(const_iterator __position, _InputIterator __first, _InputIterator __last);
|
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator insert_range(const_iterator __position, _Range&& __range) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
} else {
|
|
|
|
return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif
|
|
|
|
|
2022-08-15 14:09:49 +02:00
|
|
|
template <
|
|
|
|
class _ForwardIterator,
|
2023-05-17 10:34:51 -07:00
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> = 0>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
|
|
|
insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
insert(const_iterator __position, initializer_list<value_type> __il) {
|
|
|
|
return insert(__position, __il.begin(), __il.end());
|
|
|
|
}
|
2017-04-16 02:40:45 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
|
2014-05-08 14:14:06 +00:00
|
|
|
size_type __old_size = size();
|
2021-11-08 00:10:13 -08:00
|
|
|
__clear();
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_shrink(__old_size);
|
2011-09-14 18:33:51 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT;
|
2015-07-13 20:04:56 +00:00
|
|
|
#else
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value);
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-03 23:09:37 +01:00
|
|
|
pointer __begin_ = nullptr;
|
|
|
|
pointer __end_ = nullptr;
|
|
|
|
__compressed_pair<pointer, allocator_type> __end_cap_ =
|
|
|
|
__compressed_pair<pointer, allocator_type>(nullptr, __default_init_tag());
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-04-09 09:41:19 +02:00
|
|
|
// Allocate space for __n objects
|
|
|
|
// throws length_error if __n > max_size()
|
|
|
|
// throws (probably bad_alloc) if memory run out
|
|
|
|
// Precondition: __begin_ == __end_ == __end_cap() == 0
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Postcondition: capacity() >= __n
|
|
|
|
// Postcondition: size() == 0
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
|
2022-04-09 09:41:19 +02:00
|
|
|
if (__n > max_size())
|
|
|
|
__throw_length_error();
|
|
|
|
auto __allocation = std::__allocate_at_least(__alloc(), __n);
|
|
|
|
__begin_ = __allocation.ptr;
|
|
|
|
__end_ = __allocation.ptr;
|
|
|
|
__end_cap() = __begin_ + __allocation.count;
|
|
|
|
__annotate_new(0);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vdeallocate() _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __recommend(size_type __new_size) const;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_size(_InputIterator __first, _Sentinel __last, size_type __n) {
|
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
if (__n > 0) {
|
|
|
|
__vallocate(__n);
|
|
|
|
__construct_at_end(__first, __last, __n);
|
2022-04-09 09:41:19 +02:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
__guard.__complete();
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-15 14:09:49 +02:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
__init_with_sentinel(_InputIterator __first, _Sentinel __last) {
|
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
|
|
|
|
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
emplace_back(*__first);
|
|
|
|
|
|
|
|
__guard.__complete();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last);
|
|
|
|
|
|
|
|
template <class _ForwardIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __n);
|
|
|
|
|
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
|
|
|
__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last);
|
|
|
|
|
|
|
|
template <class _Iterator, class _Sentinel>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
|
|
|
__insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2019-03-19 19:19:44 +00:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n);
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n, const_reference __x);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator __make_iter(pointer __p) _NOEXCEPT {
|
2023-06-29 14:49:45 -07:00
|
|
|
return iterator(__p);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator __make_iter(const_pointer __p) const _NOEXCEPT {
|
2023-06-29 14:49:45 -07:00
|
|
|
return const_iterator(__p);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v);
|
2022-08-15 14:09:49 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p);
|
2012-02-26 15:30:12 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_range(pointer __from_s, pointer __from_e, pointer __to);
|
2012-02-26 15:30:12 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
|
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, false_type)
|
2015-08-18 18:57:00 +00:00
|
|
|
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT {
|
2014-05-08 14:14:06 +00:00
|
|
|
size_type __old_size = size();
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
__base_destruct_at_end(__new_last);
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_shrink(__old_size);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
template <class _Up>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline pointer __push_back_slow_path(_Up&& __x);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline pointer __emplace_back_slow_path(_Args&&... __args);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2014-05-08 14:14:06 +00:00
|
|
|
// The following functions are no-ops outside of AddressSanitizer mode.
|
2023-07-24 19:57:22 +02:00
|
|
|
// We call annotations for every allocator, unless explicitly disabled.
|
|
|
|
//
|
|
|
|
// To disable annotations for a particular allocator, change value of
|
|
|
|
// __asan_annotate_container_with_allocator to false.
|
|
|
|
// For more details, see the "Using libc++" documentation page or
|
|
|
|
// the documentation for __sanitizer_annotate_contiguous_container.
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-12-05 19:27:08 +01:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_contiguous_container(
|
2024-01-17 08:50:10 +01:00
|
|
|
const void* __old_mid, const void* __new_mid) const {
|
2023-12-13 18:05:36 -05:00
|
|
|
(void)__old_mid;
|
|
|
|
(void)__new_mid;
|
2023-12-05 19:27:08 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2024-01-17 08:50:10 +01:00
|
|
|
const void* __beg = data();
|
|
|
|
const void* __end = data() + capacity();
|
[ASan][libcxx] Annotating std::vector with all allocators
This revision is a part of a series of patches extending
AddressSanitizer C++ container overflow detection
capabilities by adding annotations, similar to those existing
in std::vector, to std::string and std::deque collections.
These changes allow ASan to detect cases when the instrumented
program accesses memory which is internally allocated by
the collection but is still not in-use (accesses before or
after the stored elements for std::deque, or between the size and
capacity bounds for std::string).
The motivation for the research and those changes was a bug,
found by Trail of Bits, in a real code where an out-of-bounds read
could happen as two strings were compared via a std::equals function
that took iter1_begin, iter1_end, iter2_begin iterators
(with a custom comparison function).
When object iter1 was longer than iter2, read out-of-bounds on iter2
could happen. Container sanitization would detect it.
In revision D132522, support for non-aligned memory buffers (sharing
first/last granule with other objects) was added, therefore the
check for standard allocator is not necessary anymore.
This patch removes the check in std::vector annotation member
function (__annotate_contiguous_container) to support
different allocators.
Additionally, this revision fixes unpoisoning in std::vector.
It guarantees that __alloc_traits::deallocate may access returned memory.
Originally suggested in D144155 revision.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
Reviewed By: #libc, #sanitizers, philnik, vitalybuka, ldionne
Spies: mikhail.ramalho, manojgupta, ldionne, AntonBikineev, ayzhao, hans, EricWF, philnik, #sanitizers, libcxx-commits
Differential Revision: https://reviews.llvm.org/D136765
2023-05-04 17:43:51 -07:00
|
|
|
if (!__libcpp_is_constant_evaluated() && __beg != nullptr &&
|
|
|
|
__asan_annotate_container_with_allocator<_Allocator>::value)
|
2014-05-08 14:14:06 +00:00
|
|
|
__sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid);
|
2016-12-23 23:37:52 +00:00
|
|
|
#endif
|
2023-12-05 19:27:08 +01:00
|
|
|
}
|
|
|
|
|
2019-07-28 04:37:02 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_new(size_type __current_size) const _NOEXCEPT {
|
2023-12-21 23:26:10 +01:00
|
|
|
(void)__current_size;
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2024-01-17 08:50:10 +01:00
|
|
|
__annotate_contiguous_container(data() + capacity(), data() + __current_size);
|
2023-12-21 23:26:10 +01:00
|
|
|
#endif
|
2014-05-08 14:14:06 +00:00
|
|
|
}
|
2016-12-23 23:37:52 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
|
2023-12-21 23:26:10 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2024-01-17 08:50:10 +01:00
|
|
|
__annotate_contiguous_container(data() + size(), data() + capacity());
|
2023-12-21 23:26:10 +01:00
|
|
|
#endif
|
2014-05-08 14:14:06 +00:00
|
|
|
}
|
2016-12-23 23:37:52 +00:00
|
|
|
|
2019-07-28 04:37:02 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_increase(size_type __n) const _NOEXCEPT {
|
2023-12-21 23:26:10 +01:00
|
|
|
(void)__n;
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2024-01-17 08:50:10 +01:00
|
|
|
__annotate_contiguous_container(data() + size(), data() + size() + __n);
|
2023-12-21 23:26:10 +01:00
|
|
|
#endif
|
2014-05-08 14:14:06 +00:00
|
|
|
}
|
2016-12-23 23:37:52 +00:00
|
|
|
|
2019-07-28 04:37:02 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_shrink(size_type __old_size) const _NOEXCEPT {
|
2023-12-21 23:26:10 +01:00
|
|
|
(void)__old_size;
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2024-01-17 08:50:10 +01:00
|
|
|
__annotate_contiguous_container(data() + __old_size, data() + size());
|
2023-12-21 23:26:10 +01:00
|
|
|
#endif
|
2014-05-08 14:14:06 +00:00
|
|
|
}
|
2019-07-28 04:37:02 +00:00
|
|
|
|
|
|
|
struct _ConstructTransaction {
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
|
2021-10-21 18:29:14 +02:00
|
|
|
: __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) {
|
2014-09-03 21:37:43 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2019-07-28 04:37:02 +00:00
|
|
|
__v_.__annotate_increase(__n);
|
|
|
|
#endif
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
|
2019-07-28 04:37:02 +00:00
|
|
|
__v_.__end_ = __pos_;
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
|
|
|
if (__pos_ != __new_end_) {
|
|
|
|
__v_.__annotate_shrink(__new_end_ - __v_.__begin_);
|
2014-09-02 23:43:38 +00:00
|
|
|
}
|
2014-09-03 21:37:43 +00:00
|
|
|
#endif
|
2019-07-28 04:37:02 +00:00
|
|
|
}
|
2014-09-03 21:37:43 +00:00
|
|
|
|
2019-07-28 04:37:02 +00:00
|
|
|
vector& __v_;
|
|
|
|
pointer __pos_;
|
|
|
|
const_pointer const __new_end_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
_ConstructTransaction(_ConstructTransaction const&) = delete;
|
|
|
|
_ConstructTransaction& operator=(_ConstructTransaction const&) = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_one_at_end(_Args&&... __args) {
|
2019-07-28 04:37:02 +00:00
|
|
|
_ConstructTransaction __tx(*this, 1);
|
2022-07-31 17:53:10 +02:00
|
|
|
__alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
|
2019-07-28 04:37:02 +00:00
|
|
|
++__tx.__pos_;
|
|
|
|
}
|
2021-11-08 00:10:13 -08:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
return this->__end_cap_.second();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
return this->__end_cap_.second();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
return this->__end_cap_.first();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
return this->__end_cap_.first();
|
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __clear() _NOEXCEPT {
|
2021-11-08 00:10:13 -08:00
|
|
|
__base_destruct_at_end(this->__begin_);
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
|
|
|
|
pointer __soon_to_be_end = this->__end_;
|
|
|
|
while (__new_last != __soon_to_be_end)
|
2022-07-31 17:53:10 +02:00
|
|
|
__alloc_traits::destroy(__alloc(), std::__to_address(--__soon_to_be_end));
|
2021-11-08 00:10:13 -08:00
|
|
|
this->__end_ = __new_last;
|
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {
|
2021-11-08 00:10:13 -08:00
|
|
|
__copy_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_copy_assignment::value>());
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c)
|
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_move_assignment::value ||
|
|
|
|
is_nothrow_move_assignable<allocator_type>::value) {
|
|
|
|
__move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
|
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2021-11-08 00:10:13 -08:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
|
|
|
|
if (__alloc() != __c.__alloc()) {
|
|
|
|
__clear();
|
[ASan][libcxx] Annotating std::vector with all allocators
This revision is a part of a series of patches extending
AddressSanitizer C++ container overflow detection
capabilities by adding annotations, similar to those existing
in std::vector, to std::string and std::deque collections.
These changes allow ASan to detect cases when the instrumented
program accesses memory which is internally allocated by
the collection but is still not in-use (accesses before or
after the stored elements for std::deque, or between the size and
capacity bounds for std::string).
The motivation for the research and those changes was a bug,
found by Trail of Bits, in a real code where an out-of-bounds read
could happen as two strings were compared via a std::equals function
that took iter1_begin, iter1_end, iter2_begin iterators
(with a custom comparison function).
When object iter1 was longer than iter2, read out-of-bounds on iter2
could happen. Container sanitization would detect it.
In revision D132522, support for non-aligned memory buffers (sharing
first/last granule with other objects) was added, therefore the
check for standard allocator is not necessary anymore.
This patch removes the check in std::vector annotation member
function (__annotate_contiguous_container) to support
different allocators.
Additionally, this revision fixes unpoisoning in std::vector.
It guarantees that __alloc_traits::deallocate may access returned memory.
Originally suggested in D144155 revision.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
Reviewed By: #libc, #sanitizers, philnik, vitalybuka, ldionne
Spies: mikhail.ramalho, manojgupta, ldionne, AntonBikineev, ayzhao, hans, EricWF, philnik, #sanitizers, libcxx-commits
Differential Revision: https://reviews.llvm.org/D136765
2023-05-04 17:43:51 -07:00
|
|
|
__annotate_delete();
|
2021-11-08 00:10:13 -08:00
|
|
|
__alloc_traits::deallocate(__alloc(), this->__begin_, capacity());
|
|
|
|
this->__begin_ = this->__end_ = __end_cap() = nullptr;
|
|
|
|
}
|
|
|
|
__alloc() = __c.__alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
|
2021-11-08 00:10:13 -08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__alloc() = std::move(__c.__alloc());
|
2021-11-08 00:10:13 -08:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2021-08-17 11:59:07 -04:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2018-05-21 21:30:12 +00:00
|
|
|
template <class _InputIterator,
|
2021-03-03 23:02:20 -05:00
|
|
|
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
|
2023-05-17 10:34:51 -07:00
|
|
|
class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
|
[libc++] Use enable_if_t instead of _EnableIf
I just ran into a compiler error involving __bind_back and some overloads
that were being disabled with _EnableIf. I noticed that the error message
was quite bad and did not mention the reason for the overload being
excluded. Specifically, the error looked like this:
candidate template ignored: substitution failure [with _Args =
<ContiguousView>]: no member named '_EnableIfImpl' in 'std::_MetaBase<false>'
Instead, when using enable_if or enable_if_t, the compiler is clever and
can produce better diagnostics, like so:
candidate template ignored: requirement 'is_invocable_v<
std::__bind_back_op<1, std::integer_sequence<unsigned long, 0>>,
std::ranges::views::__transform::__fn &, std::tuple<PlusOne> &,
ContiguousView>' was not satisfied [with _Args = <ContiguousView>]
Basically, it tries to do a poor man's implementation of concepts, which
is already a lot better than simply complaining about substitution failure.
Hence, this commit uses enable_if_t instead of _EnableIf whenever
possible. That is both more straightforward than using the internal
helper, and also leads to better error messages in those cases.
I understand the motivation for _EnableIf's implementation was to improve
compile-time performance, however I believe striving to improve error
messages is even more important for our QOI, hence this patch. Furthermore,
it is unclear that _EnableIf actually improved compile-time performance
in any noticeable way (see discussion in the review for details).
Differential Revision: https://reviews.llvm.org/D108216
2021-08-17 12:26:09 -04:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
2021-03-03 23:02:20 -05:00
|
|
|
vector(_InputIterator, _InputIterator) -> vector<__iter_value_type<_InputIterator>, _Alloc>;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-05-21 21:30:12 +00:00
|
|
|
template <class _InputIterator,
|
|
|
|
class _Alloc,
|
2023-05-17 10:34:51 -07:00
|
|
|
class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
|
[libc++] Use enable_if_t instead of _EnableIf
I just ran into a compiler error involving __bind_back and some overloads
that were being disabled with _EnableIf. I noticed that the error message
was quite bad and did not mention the reason for the overload being
excluded. Specifically, the error looked like this:
candidate template ignored: substitution failure [with _Args =
<ContiguousView>]: no member named '_EnableIfImpl' in 'std::_MetaBase<false>'
Instead, when using enable_if or enable_if_t, the compiler is clever and
can produce better diagnostics, like so:
candidate template ignored: requirement 'is_invocable_v<
std::__bind_back_op<1, std::integer_sequence<unsigned long, 0>>,
std::ranges::views::__transform::__fn &, std::tuple<PlusOne> &,
ContiguousView>' was not satisfied [with _Args = <ContiguousView>]
Basically, it tries to do a poor man's implementation of concepts, which
is already a lot better than simply complaining about substitution failure.
Hence, this commit uses enable_if_t instead of _EnableIf whenever
possible. That is both more straightforward than using the internal
helper, and also leads to better error messages in those cases.
I understand the motivation for _EnableIf's implementation was to improve
compile-time performance, however I believe striving to improve error
messages is even more important for our QOI, hence this patch. Furthermore,
it is unclear that _EnableIf actually improved compile-time performance
in any noticeable way (see discussion in the review for details).
Differential Revision: https://reviews.llvm.org/D108216
2021-08-17 12:26:09 -04:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
2021-03-03 23:02:20 -05:00
|
|
|
vector(_InputIterator, _InputIterator, _Alloc) -> vector<__iter_value_type<_InputIterator>, _Alloc>;
|
2018-05-21 21:30:12 +00:00
|
|
|
#endif
|
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <ranges::input_range _Range,
|
|
|
|
class _Alloc = allocator<ranges::range_value_t<_Range>>,
|
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
|
|
|
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
|
|
|
|
#endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_delete();
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
using _RevIter = std::reverse_iterator<pointer>;
|
|
|
|
__v.__begin_ = std::__uninitialized_allocator_move_if_noexcept(
|
|
|
|
__alloc(), _RevIter(__end_), _RevIter(__begin_), _RevIter(__v.__begin_))
|
|
|
|
.base();
|
2022-07-31 17:53:10 +02:00
|
|
|
std::swap(this->__begin_, __v.__begin_);
|
|
|
|
std::swap(this->__end_, __v.__end_);
|
|
|
|
std::swap(this->__end_cap(), __v.__end_cap());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.__first_ = __v.__begin_;
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_new(size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
|
|
|
|
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
|
[ASan][libcxx] Annotating std::vector with all allocators
This revision is a part of a series of patches extending
AddressSanitizer C++ container overflow detection
capabilities by adding annotations, similar to those existing
in std::vector, to std::string and std::deque collections.
These changes allow ASan to detect cases when the instrumented
program accesses memory which is internally allocated by
the collection but is still not in-use (accesses before or
after the stored elements for std::deque, or between the size and
capacity bounds for std::string).
The motivation for the research and those changes was a bug,
found by Trail of Bits, in a real code where an out-of-bounds read
could happen as two strings were compared via a std::equals function
that took iter1_begin, iter1_end, iter2_begin iterators
(with a custom comparison function).
When object iter1 was longer than iter2, read out-of-bounds on iter2
could happen. Container sanitization would detect it.
In revision D132522, support for non-aligned memory buffers (sharing
first/last granule with other objects) was added, therefore the
check for standard allocator is not necessary anymore.
This patch removes the check in std::vector annotation member
function (__annotate_contiguous_container) to support
different allocators.
Additionally, this revision fixes unpoisoning in std::vector.
It guarantees that __alloc_traits::deallocate may access returned memory.
Originally suggested in D144155 revision.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
Reviewed By: #libc, #sanitizers, philnik, vitalybuka, ldionne
Spies: mikhail.ramalho, manojgupta, ldionne, AntonBikineev, ayzhao, hans, EricWF, philnik, #sanitizers, libcxx-commits
Differential Revision: https://reviews.llvm.org/D136765
2023-05-04 17:43:51 -07:00
|
|
|
__annotate_delete();
|
2010-05-11 19:42:16 +00:00
|
|
|
pointer __r = __v.__begin_;
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
using _RevIter = std::reverse_iterator<pointer>;
|
|
|
|
__v.__begin_ = std::__uninitialized_allocator_move_if_noexcept(
|
|
|
|
__alloc(), _RevIter(__p), _RevIter(__begin_), _RevIter(__v.__begin_))
|
2023-12-18 14:01:33 -05:00
|
|
|
.base();
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
__v.__end_ = std::__uninitialized_allocator_move_if_noexcept(__alloc(), __p, __end_, __v.__end_);
|
2022-07-31 17:53:10 +02:00
|
|
|
std::swap(this->__begin_, __v.__begin_);
|
|
|
|
std::swap(this->__end_, __v.__end_);
|
|
|
|
std::swap(this->__end_cap(), __v.__end_cap());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.__first_ = __v.__begin_;
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_new(size());
|
2010-05-11 19:42:16 +00:00
|
|
|
return __r;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (this->__begin_ != nullptr) {
|
2023-12-18 14:01:33 -05:00
|
|
|
clear();
|
2014-05-08 14:14:06 +00:00
|
|
|
__annotate_delete();
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
__alloc_traits::deallocate(this->__alloc(), this->__begin_, capacity());
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__begin_ = this->__end_ = this->__end_cap() = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::size_type
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<_Tp, _Allocator>::max_size() const _NOEXCEPT {
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::min<size_type>(__alloc_traits::max_size(this->__alloc()), numeric_limits<difference_type>::max());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Precondition: __new_size > capacity()
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type
|
|
|
|
vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
|
|
|
|
const size_type __ms = max_size();
|
|
|
|
if (__new_size > __ms)
|
|
|
|
this->__throw_length_error();
|
|
|
|
const size_type __cap = capacity();
|
|
|
|
if (__cap >= __ms / 2)
|
|
|
|
return __ms;
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::max<size_type>(2 * __cap, __new_size);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// throws if construction throws
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Precondition: size() + __n <= capacity()
|
|
|
|
// Postcondition: size() == size() + __n
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) {
|
2019-07-28 04:37:02 +00:00
|
|
|
_ConstructTransaction __tx(*this, __n);
|
Optimize 'construct at end' loops in vector
Summary:
This change adds local 'end' and 'pos' variables for the main loop inmstead of using the ConstructTransaction variables directly.
We observed that not all vector initialization and resize operations got properly vectorized, i.e., (partially) unrolled into XMM stores for floats.
For example, `vector<int32_t> v(n, 1)` gets vectorized, but `vector<float> v(n, 1)`. It looks like the compiler assumes the state is leaked / aliased in the latter case (unclear how/why for float, but not for int32), and because of this fails to see vectorization optimization?
See https://gcc.godbolt.org/z/UWhiie
By using a local `__new_end_` (fixed), and local `__pos` (copied into __tx.__pos_ per iteration), we offer the compiler a clean loop for unrolling.
A demonstration can be seen in the isolated logic in https://gcc.godbolt.org/z/KoCNWv
The com
Reviewers: EricWF, #libc!
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D82111
2020-06-18 13:14:02 -04:00
|
|
|
const_pointer __new_end = __tx.__new_end_;
|
2021-09-07 21:35:37 -04:00
|
|
|
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__alloc_traits::construct(this->__alloc(), std::__to_address(__pos));
|
2019-07-28 04:37:02 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Copy constructs __n objects starting at __end_ from __x
|
|
|
|
// throws if construction throws
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Precondition: size() + __n <= capacity()
|
|
|
|
// Postcondition: size() == old size() + __n
|
|
|
|
// Postcondition: [i] == __x for all i in [size() - __n, __n)
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
|
2019-07-28 04:37:02 +00:00
|
|
|
_ConstructTransaction __tx(*this, __n);
|
Optimize 'construct at end' loops in vector
Summary:
This change adds local 'end' and 'pos' variables for the main loop inmstead of using the ConstructTransaction variables directly.
We observed that not all vector initialization and resize operations got properly vectorized, i.e., (partially) unrolled into XMM stores for floats.
For example, `vector<int32_t> v(n, 1)` gets vectorized, but `vector<float> v(n, 1)`. It looks like the compiler assumes the state is leaked / aliased in the latter case (unclear how/why for float, but not for int32), and because of this fails to see vectorization optimization?
See https://gcc.godbolt.org/z/UWhiie
By using a local `__new_end_` (fixed), and local `__pos` (copied into __tx.__pos_ per iteration), we offer the compiler a clean loop for unrolling.
A demonstration can be seen in the isolated logic in https://gcc.godbolt.org/z/KoCNWv
The com
Reviewers: EricWF, #libc!
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D82111
2020-06-18 13:14:02 -04:00
|
|
|
const_pointer __new_end = __tx.__new_end_;
|
2021-09-07 21:35:37 -04:00
|
|
|
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__alloc_traits::construct(this->__alloc(), std::__to_address(__pos), __x);
|
2019-07-28 04:37:02 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
2022-08-15 14:09:49 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
2023-05-08 23:40:21 -07:00
|
|
|
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 16:13:56 +02:00
|
|
|
_ConstructTransaction __tx(*this, __n);
|
|
|
|
__tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// throws if construction throws
|
|
|
|
// Postcondition: size() == size() + __n
|
2011-06-03 19:40:40 +00:00
|
|
|
// Exception safety: strong.
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n) {
|
|
|
|
if (static_cast<size_type>(this->__end_cap() - this->__end_) >= __n)
|
|
|
|
this->__construct_at_end(__n);
|
|
|
|
else {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), size(), __a);
|
|
|
|
__v.__construct_at_end(__n);
|
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// throws if construction throws
|
|
|
|
// Postcondition: size() == size() + __n
|
2011-06-03 19:40:40 +00:00
|
|
|
// Exception safety: strong.
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) {
|
|
|
|
if (static_cast<size_type>(this->__end_cap() - this->__end_) >= __n)
|
|
|
|
this->__construct_at_end(__n, __x);
|
|
|
|
else {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), size(), __a);
|
|
|
|
__v.__construct_at_end(__n, __x);
|
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) {
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n);
|
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2013-09-14 00:47:59 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2013-09-14 00:47:59 +00:00
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2013-09-14 00:47:59 +00:00
|
|
|
__construct_at_end(__n);
|
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2013-09-14 00:47:59 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2018-05-21 21:30:12 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) {
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _InputIterator,
|
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_sentinel(__first, __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _InputIterator,
|
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> >
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2022-08-15 14:09:49 +02:00
|
|
|
vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_sentinel(__first, __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _ForwardIterator,
|
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
|
|
|
__init_with_size(__first, __last, __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _ForwardIterator,
|
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> >
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2022-08-15 14:09:49 +02:00
|
|
|
vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
2023-05-08 23:40:21 -07:00
|
|
|
size_type __n = static_cast<size_type>(std::distance(__first, __last));
|
|
|
|
__init_with_size(__first, __last, __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_size(__x.__begin_, __x.__end_, __x.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2022-03-18 17:49:02 +01:00
|
|
|
vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_size(__x.__begin_, __x.__end_, __x.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x)
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2022-05-19 12:46:09 +02:00
|
|
|
noexcept
|
2015-07-14 14:46:32 +00:00
|
|
|
#else
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
2015-07-14 14:46:32 +00:00
|
|
|
#endif
|
2022-07-31 17:53:10 +02:00
|
|
|
: __end_cap_(nullptr, std::move(__x.__alloc())) {
|
2011-09-16 18:41:29 +00:00
|
|
|
this->__begin_ = __x.__begin_;
|
|
|
|
this->__end_ = __x.__end_;
|
|
|
|
this->__end_cap() = __x.__end_cap();
|
2013-06-27 19:35:32 +00:00
|
|
|
__x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
|
2022-03-18 17:49:02 +01:00
|
|
|
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__a == __x.__alloc()) {
|
|
|
|
this->__begin_ = __x.__begin_;
|
|
|
|
this->__end_ = __x.__end_;
|
|
|
|
this->__end_cap() = __x.__end_cap();
|
|
|
|
__x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr;
|
|
|
|
} else {
|
2011-11-29 18:15:50 +00:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2011-11-29 18:15:50 +00:00
|
|
|
assign(_Ip(__x.begin()), _Ip(__x.end()));
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 12:46:09 +02:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) {
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__il.size() > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__il.size());
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __il.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
|
2022-02-03 23:09:37 +01:00
|
|
|
: __end_cap_(nullptr, __a) {
|
[libc++] Improve binary size when using __transaction
__exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup code with exceptions disabled, so even if we wanted to provide the strong exception guarantees we couldn't. This is also only relevant for constructs with a stack of -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where exceptions are disabled. While -fexceptions > -fno-exceptions is quite common (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot less common, especially one that tries to catch an exception through -fno-exceptions code.
Fixes https://github.com/llvm/llvm-project/issues/56783
Reviewed By: ldionne, Mordante, huixie90, #libc
Spies: EricWF, alexfh, hans, joanahalili, libcxx-commits
Differential Revision: https://reviews.llvm.org/D133661
2022-12-08 09:40:54 +01:00
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__il.size() > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__il.size());
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __il.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2022-11-17 21:34:29 +01:00
|
|
|
__guard.__complete();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 12:46:09 +02:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>&
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::operator=(vector&& __x)
|
2024-01-30 08:33:48 -05:00
|
|
|
_NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_assign(__x, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
|
2015-08-18 18:57:00 +00:00
|
|
|
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
|
2021-11-08 00:10:13 -08:00
|
|
|
if (__alloc() != __c.__alloc()) {
|
2011-11-29 18:15:50 +00:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
assign(_Ip(__c.begin()), _Ip(__c.end()));
|
2010-05-11 19:42:16 +00:00
|
|
|
} else
|
|
|
|
__move_assign(__c, true_type());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type)
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
2021-11-08 00:10:13 -08:00
|
|
|
__move_assign_alloc(__c); // this can throw
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__begin_ = __c.__begin_;
|
|
|
|
this->__end_ = __c.__end_;
|
|
|
|
this->__end_cap() = __c.__end_cap();
|
|
|
|
__c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>&
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::operator=(const vector& __x) {
|
2022-07-31 17:53:10 +02:00
|
|
|
if (this != std::addressof(__x)) {
|
2021-11-08 00:10:13 -08:00
|
|
|
__copy_assign_alloc(__x);
|
2010-05-11 19:42:16 +00:00
|
|
|
assign(__x.__begin_, __x.__end_);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _InputIterator,
|
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> >
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__assign_with_sentinel(__first, __last);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
|
2010-05-11 19:42:16 +00:00
|
|
|
clear();
|
|
|
|
for (; __first != __last; ++__first)
|
2022-05-19 12:46:09 +02:00
|
|
|
emplace_back(*__first);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _ForwardIterator,
|
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> >
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__assign_with_size(__first, __last, std::distance(__first, __last));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
vector<_Tp, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __n) {
|
|
|
|
size_type __new_size = static_cast<size_type>(__n);
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
if (__new_size <= capacity()) {
|
|
|
|
if (__new_size > size()) {
|
2023-05-08 23:40:21 -07:00
|
|
|
_ForwardIterator __mid = std::next(__first, size());
|
|
|
|
std::copy(__first, __mid, this->__begin_);
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
__construct_at_end(__mid, __last, __new_size - size());
|
2010-05-11 19:42:16 +00:00
|
|
|
} else {
|
2023-05-08 23:40:21 -07:00
|
|
|
pointer __m = std::__copy<_ClassicAlgPolicy>(__first, __last, this->__begin_).second;
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__destruct_at_end(__m);
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__recommend(__new_size));
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
__construct_at_end(__first, __last, __new_size);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
|
|
|
|
if (__n <= capacity()) {
|
|
|
|
size_type __s = size();
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(this->__begin_, std::min(__n, __s), __u);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > __s)
|
|
|
|
__construct_at_end(__n - __s, __u);
|
|
|
|
else
|
2010-05-24 17:49:41 +00:00
|
|
|
this->__destruct_at_end(this->__begin_ + __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
} else {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__recommend(static_cast<size_type>(__n)));
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n, __u);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<_Tp, _Allocator>::begin() _NOEXCEPT {
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(this->__begin_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<_Tp, _Allocator>::begin() const _NOEXCEPT {
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(this->__begin_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<_Tp, _Allocator>::end() _NOEXCEPT {
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(this->__end_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<_Tp, _Allocator>::end() const _NOEXCEPT {
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(this->__end_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::reference
|
2019-03-15 00:29:35 +00:00
|
|
|
vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
|
2010-05-11 19:42:16 +00:00
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_reference
|
2019-03-15 00:29:35 +00:00
|
|
|
vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
|
2010-05-11 19:42:16 +00:00
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(size_type __n) {
|
|
|
|
if (__n >= size())
|
|
|
|
this->__throw_out_of_range();
|
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::const_reference
|
|
|
|
vector<_Tp, _Allocator>::at(size_type __n) const {
|
|
|
|
if (__n >= size())
|
|
|
|
this->__throw_out_of_range();
|
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __n) {
|
|
|
|
if (__n > capacity()) {
|
2021-10-21 10:40:05 +01:00
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
2010-05-11 19:42:16 +00:00
|
|
|
allocator_type& __a = this->__alloc();
|
2011-06-03 19:40:40 +00:00
|
|
|
__split_buffer<value_type, allocator_type&> __v(__n, size(), __a);
|
2010-05-11 19:42:16 +00:00
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (capacity() > size()) {
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
allocator_type& __a = this->__alloc();
|
2011-06-03 19:40:40 +00:00
|
|
|
__split_buffer<value_type, allocator_type&> __v(size(), size(), __a);
|
2010-05-11 19:42:16 +00:00
|
|
|
__swap_out_circular_buffer(__v);
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
}
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2012-02-15 00:41:34 +00:00
|
|
|
template <class _Up>
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
|
2012-02-15 00:41:34 +00:00
|
|
|
vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
2022-07-31 17:53:10 +02:00
|
|
|
// __v.push_back(std::forward<_Up>(__x));
|
|
|
|
__alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Up>(__x));
|
2013-01-11 20:36:59 +00:00
|
|
|
__v.__end_++;
|
2012-02-15 00:41:34 +00:00
|
|
|
__swap_out_circular_buffer(__v);
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
return this->__end_;
|
2012-02-15 00:41:34 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2012-02-15 00:41:34 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::push_back(const_reference __x) {
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
pointer __end = this->__end_;
|
|
|
|
if (__end < this->__end_cap()) {
|
2019-07-28 04:37:02 +00:00
|
|
|
__construct_one_at_end(__x);
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
++__end;
|
|
|
|
} else {
|
|
|
|
__end = __push_back_slow_path(__x);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
this->__end_ = __end;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void vector<_Tp, _Allocator>::push_back(value_type&& __x) {
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
pointer __end = this->__end_;
|
|
|
|
if (__end < this->__end_cap()) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__construct_one_at_end(std::move(__x));
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
++__end;
|
|
|
|
} else {
|
|
|
|
__end = __push_back_slow_path(std::move(__x));
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
this->__end_ = __end;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
|
2012-02-26 15:30:12 +00:00
|
|
|
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
2022-07-31 17:53:10 +02:00
|
|
|
// __v.emplace_back(std::forward<_Args>(__args)...);
|
|
|
|
__alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Args>(__args)...);
|
2013-01-11 20:36:59 +00:00
|
|
|
__v.__end_++;
|
2012-02-26 15:30:12 +00:00
|
|
|
__swap_out_circular_buffer(__v);
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
return this->__end_;
|
2012-02-26 15:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2016-07-21 03:20:17 +00:00
|
|
|
typename vector<_Tp, _Allocator>::reference
|
2017-01-24 23:09:12 +00:00
|
|
|
#else
|
|
|
|
void
|
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
pointer __end = this->__end_;
|
|
|
|
if (__end < this->__end_cap()) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__construct_one_at_end(std::forward<_Args>(__args)...);
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
++__end;
|
|
|
|
} else {
|
|
|
|
__end = __emplace_back_slow_path(std::forward<_Args>(__args)...);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
this->__end_ = __end;
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
[libc++] Optimize vector push_back to avoid continuous load and store of end pointer
Credits: this change is based on analysis and a proof of concept by
gerbens@google.com.
Before, the compiler loses track of end as 'this' and other references
possibly escape beyond the compiler's scope. This can be see in the
generated assembly:
16.28 │200c80: mov %r15d,(%rax)
60.87 │200c83: add $0x4,%rax
│200c87: mov %rax,-0x38(%rbp)
0.03 │200c8b: → jmpq 200d4e
...
...
1.69 │200d4e: cmp %r15d,%r12d
│200d51: → je 200c40
16.34 │200d57: inc %r15d
0.05 │200d5a: mov -0x38(%rbp),%rax
3.27 │200d5e: mov -0x30(%rbp),%r13
1.47 │200d62: cmp %r13,%rax
│200d65: → jne 200c80
We fix this by always explicitly storing the loaded local and pointer
back at the end of push back. This generates some slight source 'noise',
but creates nice and compact fast path code, i.e.:
32.64 │200760: mov %r14d,(%r12)
9.97 │200764: add $0x4,%r12
6.97 │200768: mov %r12,-0x38(%rbp)
32.17 │20076c: add $0x1,%r14d
2.36 │200770: cmp %r14d,%ebx
│200773: → je 200730
8.98 │200775: mov -0x30(%rbp),%r13
6.75 │200779: cmp %r13,%r12
│20077c: → jne 200760
Now there is a single store for the push_back value (as before), and a
single store for the end without a reload (dependency).
For fully local vectors, (i.e., not referenced elsewhere), the capacity
load and store inside the loop could also be removed, but this requires
more substantial refactoring inside vector.
Differential Revision: https://reviews.llvm.org/D80588
2023-09-13 18:16:35 -04:00
|
|
|
return *(__end - 1);
|
2017-01-24 23:09:12 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void vector<_Tp, _Allocator>::pop_back() {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__destruct_at_end(this->__end_ - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::erase(const_iterator __position) {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
2013-03-25 22:12:26 +00:00
|
|
|
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
|
2013-06-27 19:35:32 +00:00
|
|
|
difference_type __ps = __position - cbegin();
|
|
|
|
pointer __p = this->__begin_ + __ps;
|
2022-07-31 17:53:10 +02:00
|
|
|
this->__destruct_at_end(std::move(__p + 1, this->__end_, __p));
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
|
2010-05-11 19:42:16 +00:00
|
|
|
pointer __p = this->__begin_ + (__first - begin());
|
2016-12-28 06:06:09 +00:00
|
|
|
if (__first != __last) {
|
2022-07-31 17:53:10 +02:00
|
|
|
this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p));
|
2016-12-28 06:06:09 +00:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
|
|
|
|
pointer __old_last = this->__end_;
|
|
|
|
difference_type __n = __old_last - __to;
|
2019-07-28 04:37:02 +00:00
|
|
|
{
|
|
|
|
pointer __i = __from_s + __n;
|
|
|
|
_ConstructTransaction __tx(*this, __from_e - __i);
|
Optimize 'construct at end' loops in vector
Summary:
This change adds local 'end' and 'pos' variables for the main loop inmstead of using the ConstructTransaction variables directly.
We observed that not all vector initialization and resize operations got properly vectorized, i.e., (partially) unrolled into XMM stores for floats.
For example, `vector<int32_t> v(n, 1)` gets vectorized, but `vector<float> v(n, 1)`. It looks like the compiler assumes the state is leaked / aliased in the latter case (unclear how/why for float, but not for int32), and because of this fails to see vectorization optimization?
See https://gcc.godbolt.org/z/UWhiie
By using a local `__new_end_` (fixed), and local `__pos` (copied into __tx.__pos_ per iteration), we offer the compiler a clean loop for unrolling.
A demonstration can be seen in the isolated logic in https://gcc.godbolt.org/z/KoCNWv
The com
Reviewers: EricWF, #libc!
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D82111
2020-06-18 13:14:02 -04:00
|
|
|
for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
|
2019-07-28 04:37:02 +00:00
|
|
|
__alloc_traits::construct(this->__alloc(), std::__to_address(__pos), std::move(*__i));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::move_backward(__from_s, __from_s + __n, __old_last);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
|
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
[libc++] Implement P1004R2 (constexpr std::vector)
Reviewed By: #libc, ldionne
Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits
Differential Revision: https://reviews.llvm.org/D68365
2022-07-27 14:41:40 +02:00
|
|
|
// We can't compare unrelated pointers inside constant expressions
|
|
|
|
if (!__libcpp_is_constant_evaluated() && this->__end_ < this->__end_cap()) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__p == this->__end_) {
|
2019-07-28 04:37:02 +00:00
|
|
|
__construct_one_at_end(__x);
|
2010-05-11 19:42:16 +00:00
|
|
|
} else {
|
|
|
|
__move_range(__p, this->__end_, __p + 1);
|
|
|
|
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
|
|
|
|
if (__p <= __xr && __xr < this->__end_)
|
|
|
|
++__xr;
|
|
|
|
*__p = *__xr;
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2010-05-11 19:42:16 +00:00
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
|
|
|
|
__v.push_back(__x);
|
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
|
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (this->__end_ < this->__end_cap()) {
|
|
|
|
if (__p == this->__end_) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__construct_one_at_end(std::move(__x));
|
2010-05-11 19:42:16 +00:00
|
|
|
} else {
|
|
|
|
__move_range(__p, this->__end_, __p + 1);
|
2022-07-31 17:53:10 +02:00
|
|
|
*__p = std::move(__x);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2010-05-11 19:42:16 +00:00
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
|
2022-07-31 17:53:10 +02:00
|
|
|
__v.push_back(std::move(__x));
|
2010-05-11 19:42:16 +00:00
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
|
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (this->__end_ < this->__end_cap()) {
|
|
|
|
if (__p == this->__end_) {
|
2022-07-31 17:53:10 +02:00
|
|
|
__construct_one_at_end(std::forward<_Args>(__args)...);
|
2010-05-11 19:42:16 +00:00
|
|
|
} else {
|
2022-07-31 17:53:10 +02:00
|
|
|
__temp_value<value_type, _Allocator> __tmp(this->__alloc(), std::forward<_Args>(__args)...);
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_range(__p, this->__end_, __p + 1);
|
2022-07-31 17:53:10 +02:00
|
|
|
*__p = std::move(__tmp.get());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2010-05-11 19:42:16 +00:00
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
|
2022-07-31 17:53:10 +02:00
|
|
|
__v.emplace_back(std::forward<_Args>(__args)...);
|
2010-05-11 19:42:16 +00:00
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
|
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (__n > 0) {
|
[libc++] Implement P1004R2 (constexpr std::vector)
Reviewed By: #libc, ldionne
Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits
Differential Revision: https://reviews.llvm.org/D68365
2022-07-27 14:41:40 +02:00
|
|
|
// We can't compare unrelated pointers inside constant expressions
|
|
|
|
if (!__libcpp_is_constant_evaluated() && __n <= static_cast<size_type>(this->__end_cap() - this->__end_)) {
|
2010-05-11 19:42:16 +00:00
|
|
|
size_type __old_n = __n;
|
|
|
|
pointer __old_last = this->__end_;
|
|
|
|
if (__n > static_cast<size_type>(this->__end_ - __p)) {
|
|
|
|
size_type __cx = __n - (this->__end_ - __p);
|
|
|
|
__construct_at_end(__cx, __x);
|
|
|
|
__n -= __cx;
|
|
|
|
}
|
|
|
|
if (__n > 0) {
|
|
|
|
__move_range(__p, __old_last, __p + __old_n);
|
|
|
|
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
|
|
|
|
if (__p <= __xr && __xr < this->__end_)
|
|
|
|
__xr += __old_n;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(__p, __n, *__xr);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, __a);
|
|
|
|
__v.__construct_at_end(__n, __x);
|
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _InputIterator,
|
|
|
|
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
return __insert_with_sentinel(__position, __first, __last);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
|
2010-05-11 19:42:16 +00:00
|
|
|
difference_type __off = __position - begin();
|
|
|
|
pointer __p = this->__begin_ + __off;
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
pointer __old_last = this->__end_;
|
|
|
|
for (; this->__end_ != this->__end_cap() && __first != __last; ++__first) {
|
2019-07-28 04:37:02 +00:00
|
|
|
__construct_one_at_end(*__first);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__a);
|
|
|
|
if (__first != __last) {
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-05-08 23:40:21 -07:00
|
|
|
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
|
2010-05-11 19:42:16 +00:00
|
|
|
difference_type __old_size = __old_last - this->__begin_;
|
|
|
|
difference_type __old_p = __p - this->__begin_;
|
|
|
|
reserve(__recommend(size() + __v.size()));
|
|
|
|
__p = this->__begin_ + __old_p;
|
|
|
|
__old_last = this->__begin_ + __old_size;
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
2022-11-14 11:01:05 -10:00
|
|
|
erase(__make_iter(__old_last), end());
|
2010-05-11 19:42:16 +00:00
|
|
|
throw;
|
|
|
|
}
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
__p = std::rotate(__p, __old_last, this->__end_);
|
2022-11-14 11:01:05 -10:00
|
|
|
insert(__make_iter(__p), std::make_move_iterator(__v.begin()), std::make_move_iterator(__v.end()));
|
2010-05-11 19:42:16 +00:00
|
|
|
return begin() + __off;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2023-05-17 10:34:51 -07:00
|
|
|
template <class _ForwardIterator,
|
|
|
|
__enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value &&
|
2022-08-15 14:09:49 +02:00
|
|
|
is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
return __insert_with_size(__position, __first, __last, std::distance(__first, __last));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::__insert_with_size(
|
|
|
|
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
|
|
|
|
auto __insertion_size = __n;
|
2010-05-11 19:42:16 +00:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (__n > 0) {
|
|
|
|
if (__n <= this->__end_cap() - this->__end_) {
|
|
|
|
size_type __old_n = __n;
|
|
|
|
pointer __old_last = this->__end_;
|
2023-05-08 23:40:21 -07:00
|
|
|
_Iterator __m = std::next(__first, __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
difference_type __dx = this->__end_ - __p;
|
|
|
|
if (__n > __dx) {
|
|
|
|
__m = __first;
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
difference_type __diff = this->__end_ - __p;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::advance(__m, __diff);
|
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary:
In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a
very large slowdown compared to libstdc++.
This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions.
This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`.
This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`.
On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`.
Reviewers: howard.hinnant, titus, kcc, mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D8109
llvm-svn: 233711
2015-03-31 16:54:19 +00:00
|
|
|
__construct_at_end(__m, __last, __n - __diff);
|
2010-05-11 19:42:16 +00:00
|
|
|
__n = __dx;
|
|
|
|
}
|
|
|
|
if (__n > 0) {
|
|
|
|
__move_range(__p, __old_last, __p + __old_n);
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy(__first, __m, __p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, __a);
|
2023-05-08 23:40:21 -07:00
|
|
|
__v.__construct_at_end_with_size(__first, __insertion_size);
|
2010-05-11 19:42:16 +00:00
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-11-14 11:01:05 -10:00
|
|
|
return __make_iter(__p);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __sz) {
|
|
|
|
size_type __cs = size();
|
|
|
|
if (__cs < __sz)
|
|
|
|
this->__append(__sz - __cs);
|
|
|
|
else if (__cs > __sz)
|
|
|
|
this->__destruct_at_end(this->__begin_ + __sz);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) {
|
|
|
|
size_type __cs = size();
|
|
|
|
if (__cs < __sz)
|
|
|
|
this->__append(__sz - __cs, __x);
|
|
|
|
else if (__cs > __sz)
|
|
|
|
this->__destruct_at_end(this->__begin_ + __sz);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT
|
2015-07-13 20:04:56 +00:00
|
|
|
#else
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value)
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
{
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
|
|
|
|
__alloc_traits::propagate_on_container_swap::value || this->__alloc() == __x.__alloc(),
|
|
|
|
"vector::swap: Either propagate_on_container_swap must be true"
|
|
|
|
" or the allocators must compare equal");
|
2022-07-31 17:53:10 +02:00
|
|
|
std::swap(this->__begin_, __x.__begin_);
|
|
|
|
std::swap(this->__end_, __x.__end_);
|
|
|
|
std::swap(this->__end_cap(), __x.__end_cap());
|
|
|
|
std::__swap_allocator(
|
2015-07-13 20:04:56 +00:00
|
|
|
this->__alloc(), __x.__alloc(), integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
|
2013-06-27 19:35:32 +00:00
|
|
|
if (this->__begin_ == nullptr) {
|
|
|
|
if (this->__end_ != nullptr || this->__end_cap() != nullptr)
|
2010-05-11 19:42:16 +00:00
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if (this->__begin_ > this->__end_)
|
|
|
|
return false;
|
|
|
|
if (this->__begin_ == this->__end_cap())
|
|
|
|
return false;
|
|
|
|
if (this->__end_ > this->__end_cap())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// vector<bool>
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
class vector<bool, _Allocator>;
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
struct hash<vector<bool, _Allocator> >;
|
|
|
|
|
2011-07-02 20:33:23 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
struct __has_storage_type<vector<bool, _Allocator> > {
|
|
|
|
static const bool value = true;
|
|
|
|
};
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Allocator>
|
2017-01-04 23:56:00 +00:00
|
|
|
class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator> {
|
2010-05-11 19:42:16 +00:00
|
|
|
public:
|
|
|
|
typedef vector __self;
|
2010-08-22 00:02:43 +00:00
|
|
|
typedef bool value_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef _Allocator allocator_type;
|
|
|
|
typedef allocator_traits<allocator_type> __alloc_traits;
|
|
|
|
typedef typename __alloc_traits::size_type size_type;
|
|
|
|
typedef typename __alloc_traits::difference_type difference_type;
|
2012-05-07 16:50:38 +00:00
|
|
|
typedef size_type __storage_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef __bit_iterator<vector, false> pointer;
|
|
|
|
typedef __bit_iterator<vector, true> const_pointer;
|
|
|
|
typedef pointer iterator;
|
|
|
|
typedef const_pointer const_iterator;
|
2022-07-31 17:53:10 +02:00
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
private:
|
2022-10-08 22:17:32 +02:00
|
|
|
typedef __rebind_alloc<__alloc_traits, __storage_type> __storage_allocator;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef allocator_traits<__storage_allocator> __storage_traits;
|
|
|
|
typedef typename __storage_traits::pointer __storage_pointer;
|
|
|
|
typedef typename __storage_traits::const_pointer __const_storage_pointer;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
__storage_pointer __begin_;
|
|
|
|
size_type __size_;
|
|
|
|
__compressed_pair<size_type, __storage_allocator> __cap_alloc_;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2011-07-09 15:50:42 +00:00
|
|
|
public:
|
2011-07-02 20:33:23 +00:00
|
|
|
typedef __bit_reference<vector> reference;
|
2022-04-09 09:48:21 +02:00
|
|
|
#ifdef _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
|
|
|
|
using const_reference = bool;
|
|
|
|
#else
|
2011-07-02 20:33:23 +00:00
|
|
|
typedef __bit_const_reference<vector> const_reference;
|
2022-04-09 09:48:21 +02:00
|
|
|
#endif
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2011-07-09 15:50:42 +00:00
|
|
|
private:
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type& __cap() _NOEXCEPT { return __cap_alloc_.first(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const size_type& __cap() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __cap_alloc_.first();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __storage_allocator& __alloc() _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __cap_alloc_.second();
|
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const __storage_allocator& __alloc() const _NOEXCEPT {
|
|
|
|
return __cap_alloc_.second();
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
static const unsigned __bits_per_word = static_cast<unsigned>(sizeof(__storage_type) * CHAR_BIT);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type
|
2011-06-03 19:40:40 +00:00
|
|
|
__internal_cap_to_external(size_type __n) _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return __n * __bits_per_word;
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type
|
2011-06-03 19:40:40 +00:00
|
|
|
__external_cap_to_internal(size_type __n) _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return (__n - 1) / __bits_per_word + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector()
|
2015-06-04 02:05:41 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value);
|
2015-06-04 00:10:20 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(const allocator_type& __a)
|
2015-06-04 00:10:20 +00:00
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
|
|
|
|
#else
|
|
|
|
_NOEXCEPT;
|
|
|
|
#endif
|
2022-11-17 21:34:29 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
class __destroy_vector {
|
|
|
|
public:
|
2023-01-23 10:27:14 +01:00
|
|
|
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
|
2022-11-17 21:34:29 +01:00
|
|
|
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
|
|
|
|
if (__vec_.__begin_ != nullptr)
|
|
|
|
__storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
vector& __vec_;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~vector() { __destroy_vector (*this)(); }
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n);
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n, const allocator_type& __a);
|
2013-09-14 00:47:59 +00:00
|
|
|
#endif
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(size_type __n, const value_type& __v);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
vector(size_type __n, const value_type& __v, const allocator_type& __a);
|
2023-08-18 13:08:04 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
|
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<bool> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr vector(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type())
|
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
__init_with_sentinel(ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v, const allocator_type& __a);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(const vector& __v);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(initializer_list<value_type> __il);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-05-19 12:46:09 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(initializer_list<value_type> __il) {
|
|
|
|
assign(__il.begin(), __il.end());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(vector&& __v)
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2022-05-19 12:46:09 +02:00
|
|
|
noexcept;
|
2015-07-14 14:46:32 +00:00
|
|
|
#else
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
2015-07-14 14:46:32 +00:00
|
|
|
#endif
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
vector(vector&& __v, const __type_identity_t<allocator_type>& __a);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector& operator=(vector&& __v)
|
2024-01-30 08:33:48 -05:00
|
|
|
_NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
2022-08-19 13:08:01 +02:00
|
|
|
void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_InputIterator __first, _InputIterator __last);
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
2022-08-19 13:08:01 +02:00
|
|
|
void _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_ForwardIterator __first, _ForwardIterator __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<bool> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void assign_range(_Range&& __range) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
__assign_with_size(ranges::begin(__range), ranges::end(__range), __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
} else {
|
|
|
|
__assign_with_sentinel(ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void assign(size_type __n, const value_type& __x);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void assign(initializer_list<value_type> __il) {
|
2010-05-11 19:42:16 +00:00
|
|
|
assign(__il.begin(), __il.end());
|
|
|
|
}
|
2017-04-16 02:40:45 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return allocator_type(this->__alloc());
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT;
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __internal_cap_to_external(__cap());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { return __size_; }
|
|
|
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __size_ == 0;
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __n);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT { return __make_iter(0); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT { return __make_iter(0); }
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT { return __make_iter(__size_); }
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __make_iter(__size_);
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return reverse_iterator(end());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return const_reverse_iterator(end());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return reverse_iterator(begin());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return const_reverse_iterator(begin());
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT { return __make_iter(0); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return __make_iter(__size_);
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT {
|
2011-06-03 19:40:40 +00:00
|
|
|
return rbegin();
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __n) { return __make_ref(__n); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __n) const {
|
|
|
|
return __make_ref(__n);
|
|
|
|
}
|
2022-08-17 11:17:34 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference at(size_type __n);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() { return __make_ref(0); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const { return __make_ref(0); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() { return __make_ref(__size_ - 1); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const { return __make_ref(__size_ - 1); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(const value_type& __x);
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2013-08-13 23:54:12 +00:00
|
|
|
template <class... _Args>
|
2023-02-14 00:56:09 +01:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference emplace_back(_Args&&... __args)
|
2017-01-24 23:09:12 +00:00
|
|
|
# else
|
2022-07-31 17:53:10 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args)
|
2017-01-24 23:09:12 +00:00
|
|
|
# endif
|
|
|
|
{
|
2022-07-31 17:53:10 +02:00
|
|
|
push_back(value_type(std::forward<_Args>(__args)...));
|
2023-02-14 00:56:09 +01:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2016-07-21 03:20:17 +00:00
|
|
|
return this->back();
|
2017-01-24 23:09:12 +00:00
|
|
|
# endif
|
2016-07-21 03:20:17 +00:00
|
|
|
}
|
2013-08-13 23:54:12 +00:00
|
|
|
#endif
|
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<bool> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
|
|
|
|
insert_range(end(), std::forward<_Range>(__range));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() { --__size_; }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2013-08-13 23:54:12 +00:00
|
|
|
template <class... _Args>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator emplace(const_iterator __position, _Args&&... __args) {
|
2022-07-31 17:53:10 +02:00
|
|
|
return insert(__position, value_type(std::forward<_Args>(__args)...));
|
|
|
|
}
|
2013-08-13 23:54:12 +00:00
|
|
|
#endif
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, const value_type& __x);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
|
|
|
insert(const_iterator __position, size_type __n, const value_type& __x);
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0>
|
2022-08-19 13:08:01 +02:00
|
|
|
iterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
insert(const_iterator __position, _InputIterator __first, _InputIterator __last);
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
2022-08-19 13:08:01 +02:00
|
|
|
iterator _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
|
insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last);
|
2017-04-16 02:40:45 +00:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<bool> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator insert_range(const_iterator __position, _Range&& __range) {
|
|
|
|
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
|
|
|
|
auto __n = static_cast<size_type>(ranges::distance(__range));
|
|
|
|
return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
} else {
|
|
|
|
return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif
|
|
|
|
|
2017-04-16 02:40:45 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
insert(const_iterator __position, initializer_list<value_type> __il) {
|
|
|
|
return insert(__position, __il.begin(), __il.end());
|
|
|
|
}
|
2017-04-16 02:40:45 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __position);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __first, const_iterator __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT { __size_ = 0; }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 10:27:14 +01:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(vector&)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
|
|
_NOEXCEPT;
|
|
|
|
#else
|
2016-12-28 06:06:09 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value);
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void swap(reference __x, reference __y) _NOEXCEPT {
|
|
|
|
std::swap(__x, __y);
|
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __sz, value_type __x = false);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-03 23:09:37 +01:00
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); }
|
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); }
|
|
|
|
|
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
|
|
__init_with_size(_InputIterator __first, _Sentinel __last, size_type __n) {
|
|
|
|
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
|
|
|
|
|
|
|
|
if (__n > 0) {
|
|
|
|
__vallocate(__n);
|
|
|
|
__construct_at_end(std::move(__first), std::move(__last), __n);
|
|
|
|
}
|
|
|
|
|
2022-07-31 17:53:10 +02:00
|
|
|
__guard.__complete();
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
|
|
__init_with_sentinel(_InputIterator __first, _Sentinel __last) {
|
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
|
|
|
try {
|
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
push_back(*__first);
|
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
|
|
|
} catch (...) {
|
|
|
|
if (__begin_ != nullptr)
|
|
|
|
__storage_traits::deallocate(__alloc(), __begin_, __cap());
|
|
|
|
throw;
|
|
|
|
}
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last);
|
|
|
|
|
|
|
|
template <class _ForwardIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __ns);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
2022-08-15 14:09:49 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
2023-05-08 23:40:21 -07:00
|
|
|
__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _Iterator, class _Sentinel>
|
2022-08-15 14:09:49 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator
|
2023-05-08 23:40:21 -07:00
|
|
|
__insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-04-09 09:41:19 +02:00
|
|
|
// Allocate space for __n objects
|
|
|
|
// throws length_error if __n > max_size()
|
|
|
|
// throws (probably bad_alloc) if memory run out
|
|
|
|
// Precondition: __begin_ == __end_ == __cap() == 0
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Postcondition: capacity() >= __n
|
|
|
|
// Postcondition: size() == 0
|
2023-05-08 23:40:21 -07:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vallocate(size_type __n) {
|
2022-04-09 09:41:19 +02:00
|
|
|
if (__n > max_size())
|
|
|
|
__throw_length_error();
|
|
|
|
auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n));
|
|
|
|
__begin_ = __allocation.ptr;
|
|
|
|
__size_ = 0;
|
|
|
|
__cap() = __allocation.count;
|
[libc++] Implement P1004R2 (constexpr std::vector)
Reviewed By: #libc, ldionne
Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits
Differential Revision: https://reviews.llvm.org/D68365
2022-07-27 14:41:40 +02:00
|
|
|
if (__libcpp_is_constant_evaluated()) {
|
|
|
|
for (size_type __i = 0; __i != __cap(); ++__i)
|
|
|
|
std::__construct_at(std::__to_address(__begin_) + __i);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vdeallocate() _NOEXCEPT;
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type __align_it(size_type __new_size) _NOEXCEPT {
|
2022-03-03 13:39:12 -05:00
|
|
|
return (__new_size + (__bits_per_word - 1)) & ~((size_type)__bits_per_word - 1);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __new_size) const;
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_at_end(size_type __n, bool __x);
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
|
|
__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append(size_type __n, const_reference __x);
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference __make_ref(size_type __pos) _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference __make_ref(size_type __pos) const _NOEXCEPT {
|
2022-04-09 09:48:21 +02:00
|
|
|
return __bit_const_reference<vector>(
|
2010-05-11 19:42:16 +00:00
|
|
|
__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iter(size_type __pos) _NOEXCEPT {
|
2023-05-08 23:40:21 -07:00
|
|
|
return iterator(__begin_ + __pos / __bits_per_word, static_cast<unsigned>(__pos % __bits_per_word));
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_iter(size_type __pos) const _NOEXCEPT {
|
2023-05-08 23:40:21 -07:00
|
|
|
return const_iterator(__begin_ + __pos / __bits_per_word, static_cast<unsigned>(__pos % __bits_per_word));
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __const_iterator_cast(const_iterator __p) _NOEXCEPT {
|
2013-06-27 19:35:32 +00:00
|
|
|
return begin() + (__p - cbegin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector& __v) {
|
|
|
|
__copy_assign_alloc(
|
|
|
|
__v, integral_constant<bool, __storage_traits::propagate_on_container_copy_assignment::value>());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector& __c, true_type) {
|
2022-04-09 09:41:19 +02:00
|
|
|
if (__alloc() != __c.__alloc())
|
|
|
|
__vdeallocate();
|
|
|
|
__alloc() = __c.__alloc();
|
[libc++] Implement P1004R2 (constexpr std::vector)
Reviewed By: #libc, ldionne
Spies: mgorny, var-const, ormris, philnik, miscco, hiraditya, steven_wu, jkorous, ldionne, christof, libcxx-commits
Differential Revision: https://reviews.llvm.org/D68365
2022-07-27 14:41:40 +02:00
|
|
|
}
|
2022-04-09 09:41:19 +02:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector&, false_type) {}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(vector& __c, false_type);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(vector& __c, true_type)
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector& __c)
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(!__storage_traits::propagate_on_container_move_assignment::value ||
|
|
|
|
is_nothrow_move_assignable<allocator_type>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_assign_alloc(
|
2015-07-13 20:04:56 +00:00
|
|
|
__c, integral_constant<bool, __storage_traits::propagate_on_container_move_assignment::value>());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector& __c, true_type)
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
|
2022-08-19 13:08:01 +02:00
|
|
|
__alloc() = std::move(__c.__alloc());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_t __hash_code() const _NOEXCEPT;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
friend class __bit_reference<vector>;
|
|
|
|
friend class __bit_const_reference<vector>;
|
|
|
|
friend class __bit_iterator<vector, false>;
|
|
|
|
friend class __bit_iterator<vector, true>;
|
2012-08-17 17:10:18 +00:00
|
|
|
friend struct __bit_array<vector>;
|
2017-01-04 23:56:00 +00:00
|
|
|
friend struct _LIBCPP_TEMPLATE_VIS hash<vector>;
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2018-05-22 16:20:28 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::__vdeallocate() _NOEXCEPT {
|
2013-06-27 19:35:32 +00:00
|
|
|
if (this->__begin_ != nullptr) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__storage_traits::deallocate(this->__alloc(), this->__begin_, __cap());
|
2013-06-27 19:35:32 +00:00
|
|
|
this->__begin_ = nullptr;
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__size_ = this->__cap() = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::size_type
|
2011-06-03 19:40:40 +00:00
|
|
|
vector<bool, _Allocator>::max_size() const _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
size_type __amax = __storage_traits::max_size(__alloc());
|
|
|
|
size_type __nmax = numeric_limits<size_type>::max() / 2; // end() >= begin(), always
|
|
|
|
if (__nmax / __bits_per_word <= __amax)
|
|
|
|
return __nmax;
|
|
|
|
return __internal_cap_to_external(__amax);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Precondition: __new_size > capacity()
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::size_type
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::__recommend(size_type __new_size) const {
|
|
|
|
const size_type __ms = max_size();
|
|
|
|
if (__new_size > __ms)
|
|
|
|
this->__throw_length_error();
|
|
|
|
const size_type __cap = capacity();
|
|
|
|
if (__cap >= __ms / 2)
|
|
|
|
return __ms;
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::max(2 * __cap, __align_it(__new_size));
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Precondition: size() + __n <= capacity()
|
|
|
|
// Postcondition: size() == size() + __n
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::__construct_at_end(size_type __n, bool __x) {
|
|
|
|
size_type __old_size = this->__size_;
|
|
|
|
this->__size_ += __n;
|
2018-10-23 20:07:45 +00:00
|
|
|
if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) {
|
|
|
|
if (this->__size_ <= __bits_per_word)
|
|
|
|
this->__begin_[0] = __storage_type(0);
|
|
|
|
else
|
|
|
|
this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0);
|
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(__make_iter(__old_size), __n, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-05-08 23:40:21 -07:00
|
|
|
template <class _InputIterator, class _Sentinel>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
2023-05-08 23:40:21 -07:00
|
|
|
vector<bool, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
|
2010-05-11 19:42:16 +00:00
|
|
|
size_type __old_size = this->__size_;
|
2023-05-08 23:40:21 -07:00
|
|
|
this->__size_ += __n;
|
2018-10-23 20:07:45 +00:00
|
|
|
if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) {
|
|
|
|
if (this->__size_ <= __bits_per_word)
|
|
|
|
this->__begin_[0] = __storage_type(0);
|
|
|
|
else
|
|
|
|
this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0);
|
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
std::__copy<_ClassicAlgPolicy>(__first, __last, __make_iter(__old_size));
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector()
|
2015-06-04 02:05:41 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const allocator_type& __a)
|
2015-06-04 00:10:20 +00:00
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
|
|
|
|
#else
|
|
|
|
_NOEXCEPT
|
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2013-09-14 00:47:59 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, const allocator_type& __a)
|
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2013-09-14 00:47:59 +00:00
|
|
|
__construct_at_end(__n, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, const value_type& __x)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a)
|
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-18 13:08:04 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_sentinel(__first, __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-18 13:08:04 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2023-08-18 13:08:04 -07:00
|
|
|
vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
|
2010-05-11 19:42:16 +00:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__init_with_sentinel(__first, __last);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-18 13:08:04 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
|
2023-05-08 23:40:21 -07:00
|
|
|
auto __n = static_cast<size_type>(std::distance(__first, __last));
|
|
|
|
__init_with_size(__first, __last, __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-18 13:08:04 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2023-08-18 13:08:04 -07:00
|
|
|
vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
|
2010-05-11 19:42:16 +00:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
2023-05-08 23:40:21 -07:00
|
|
|
auto __n = static_cast<size_type>(std::distance(__first, __last));
|
|
|
|
__init_with_size(__first, __last, __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-16 02:40:45 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2011-08-12 21:56:02 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(initializer_list<value_type> __il)
|
2019-12-16 18:23:39 -05:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) {
|
2010-05-11 19:42:16 +00:00
|
|
|
size_type __n = static_cast<size_type>(__il.size());
|
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
|
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) {
|
|
|
|
size_type __n = static_cast<size_type>(__il.size());
|
|
|
|
if (__n > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__n);
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-20 12:03:32 -04:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2011-08-12 21:56:02 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v)
|
2013-06-27 19:35:32 +00:00
|
|
|
: __begin_(nullptr),
|
2010-05-11 19:42:16 +00:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, __storage_traits::select_on_container_copy_construction(__v.__alloc())) {
|
|
|
|
if (__v.size() > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__v.size());
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__v.begin(), __v.end(), __v.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v, const allocator_type& __a)
|
2013-06-27 19:35:32 +00:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__v.size() > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__v.size());
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__v.begin(), __v.end(), __v.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>& vector<bool, _Allocator>::operator=(const vector& __v) {
|
2022-07-31 17:53:10 +02:00
|
|
|
if (this != std::addressof(__v)) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__copy_assign_alloc(__v);
|
|
|
|
if (__v.__size_) {
|
|
|
|
if (__v.__size_ > capacity()) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__v.__size_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy(__v.__begin_, __v.__begin_ + __external_cap_to_internal(__v.__size_), __begin_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
__size_ = __v.__size_;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(vector&& __v)
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2018-06-05 22:32:52 +00:00
|
|
|
_NOEXCEPT
|
2015-07-14 14:46:32 +00:00
|
|
|
#else
|
2018-06-05 22:32:52 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
2015-07-14 14:46:32 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
: __begin_(__v.__begin_),
|
|
|
|
__size_(__v.__size_),
|
2022-07-31 17:53:10 +02:00
|
|
|
__cap_alloc_(std::move(__v.__cap_alloc_)) {
|
2013-06-27 19:35:32 +00:00
|
|
|
__v.__begin_ = nullptr;
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.__size_ = 0;
|
|
|
|
__v.__cap() = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
2022-03-18 17:49:02 +01:00
|
|
|
vector<bool, _Allocator>::vector(vector&& __v, const __type_identity_t<allocator_type>& __a)
|
2013-06-27 19:35:32 +00:00
|
|
|
: __begin_(nullptr), __size_(0), __cap_alloc_(0, __a) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__a == allocator_type(__v.__alloc())) {
|
|
|
|
this->__begin_ = __v.__begin_;
|
|
|
|
this->__size_ = __v.__size_;
|
|
|
|
this->__cap() = __v.__cap();
|
|
|
|
__v.__begin_ = nullptr;
|
|
|
|
__v.__cap() = __v.__size_ = 0;
|
|
|
|
} else if (__v.size() > 0) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vallocate(__v.size());
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__v.begin(), __v.end(), __v.size());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>&
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::operator=(vector&& __v)
|
2024-01-30 08:33:48 -05:00
|
|
|
_NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_assign(__v, integral_constant<bool, __storage_traits::propagate_on_container_move_assignment::value>());
|
2012-10-13 02:03:45 +00:00
|
|
|
return *this;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::__move_assign(vector& __c, false_type) {
|
|
|
|
if (__alloc() != __c.__alloc())
|
|
|
|
assign(__c.begin(), __c.end());
|
|
|
|
else
|
|
|
|
__move_assign(__c, true_type());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::__move_assign(vector& __c, true_type)
|
2011-06-03 19:40:40 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
2014-07-21 15:15:15 +00:00
|
|
|
__move_assign_alloc(__c);
|
2010-05-11 19:42:16 +00:00
|
|
|
this->__begin_ = __c.__begin_;
|
|
|
|
this->__size_ = __c.__size_;
|
|
|
|
this->__cap() = __c.__cap();
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
__c.__cap() = __c.__size_ = 0;
|
|
|
|
}
|
2010-09-04 23:28:19 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::assign(size_type __n, const value_type& __x) {
|
|
|
|
__size_ = 0;
|
|
|
|
if (__n > 0) {
|
|
|
|
size_type __c = capacity();
|
|
|
|
if (__n <= __c)
|
|
|
|
__size_ = __n;
|
|
|
|
else {
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.reserve(__recommend(__n));
|
|
|
|
__v.__size_ = __n;
|
|
|
|
swap(__v);
|
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(begin(), __n, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::assign(_InputIterator __first, _InputIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__assign_with_sentinel(__first, __last);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
vector<bool, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
|
2010-05-11 19:42:16 +00:00
|
|
|
clear();
|
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
push_back(*__first);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
__assign_with_size(__first, __last, std::distance(__first, __last));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
|
|
vector<bool, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __ns) {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__ns >= 0, "invalid range specified");
|
2023-05-08 23:40:21 -07:00
|
|
|
|
|
|
|
clear();
|
|
|
|
|
2016-12-23 23:37:52 +00:00
|
|
|
const size_t __n = static_cast<size_type>(__ns);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n) {
|
|
|
|
if (__n > capacity()) {
|
2018-05-22 16:20:28 +00:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
__construct_at_end(__first, __last, __n);
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::reserve(size_type __n) {
|
|
|
|
if (__n > capacity()) {
|
2021-10-21 10:40:05 +01:00
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(this->get_allocator());
|
2018-05-22 16:20:28 +00:00
|
|
|
__v.__vallocate(__n);
|
2023-05-08 23:40:21 -07:00
|
|
|
__v.__construct_at_end(this->begin(), this->end(), this->size());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::shrink_to_fit() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__external_cap_to_internal(size()) > __cap()) {
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
vector(*this, allocator_type(__alloc())).swap(*this);
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
typename vector<bool, _Allocator>::reference vector<bool, _Allocator>::at(size_type __n) {
|
|
|
|
if (__n >= size())
|
|
|
|
this->__throw_out_of_range();
|
|
|
|
return (*this)[__n];
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
typename vector<bool, _Allocator>::const_reference vector<bool, _Allocator>::at(size_type __n) const {
|
|
|
|
if (__n >= size())
|
|
|
|
this->__throw_out_of_range();
|
|
|
|
return (*this)[__n];
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::push_back(const value_type& __x) {
|
|
|
|
if (this->__size_ == this->capacity())
|
|
|
|
reserve(__recommend(this->__size_ + 1));
|
|
|
|
++this->__size_;
|
|
|
|
back() = __x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, const value_type& __x) {
|
|
|
|
iterator __r;
|
|
|
|
if (size() < capacity()) {
|
|
|
|
const_iterator __old_end = end();
|
|
|
|
++__size_;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy_backward(__position, __old_end, end());
|
2010-05-11 19:42:16 +00:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
} else {
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.reserve(__recommend(__size_ + 1));
|
|
|
|
__v.__size_ = __size_ + 1;
|
2022-07-31 17:53:10 +02:00
|
|
|
__r = std::copy(cbegin(), __position, __v.begin());
|
|
|
|
std::copy_backward(__position, cend(), __v.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__v);
|
|
|
|
}
|
|
|
|
*__r = __x;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, size_type __n, const value_type& __x) {
|
|
|
|
iterator __r;
|
|
|
|
size_type __c = capacity();
|
|
|
|
if (__n <= __c && size() <= __c - __n) {
|
|
|
|
const_iterator __old_end = end();
|
|
|
|
__size_ += __n;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy_backward(__position, __old_end, end());
|
2010-05-11 19:42:16 +00:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
} else {
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2022-07-31 17:53:10 +02:00
|
|
|
__r = std::copy(cbegin(), __position, __v.begin());
|
|
|
|
std::copy_backward(__position, cend(), __v.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__v);
|
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(__r, __n, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
return __insert_with_sentinel(__position, __first, __last);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _InputIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<bool, _Allocator>::iterator
|
|
|
|
vector<bool, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
|
2010-05-11 19:42:16 +00:00
|
|
|
difference_type __off = __position - begin();
|
|
|
|
iterator __p = __const_iterator_cast(__position);
|
|
|
|
iterator __old_end = end();
|
|
|
|
for (; size() != capacity() && __first != __last; ++__first) {
|
|
|
|
++this->__size_;
|
|
|
|
back() = *__first;
|
|
|
|
}
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__first != __last) {
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 11:47:01 +01:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-05-08 23:40:21 -07:00
|
|
|
__v.__assign_with_sentinel(std::move(__first), std::move(__last));
|
2010-05-11 19:42:16 +00:00
|
|
|
difference_type __old_size = static_cast<difference_type>(__old_end - begin());
|
|
|
|
difference_type __old_p = __p - begin();
|
|
|
|
reserve(__recommend(size() + __v.size()));
|
|
|
|
__p = begin() + __old_p;
|
|
|
|
__old_end = begin() + __old_size;
|
2023-02-02 11:47:01 +01:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
erase(__old_end, end());
|
|
|
|
throw;
|
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
__p = std::rotate(__p, __old_end, end());
|
2010-05-11 19:42:16 +00:00
|
|
|
insert(__p, __v.begin(), __v.end());
|
|
|
|
return begin() + __off;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2023-08-15 12:19:05 -07:00
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) {
|
2023-05-08 23:40:21 -07:00
|
|
|
return __insert_with_size(__position, __first, __last, std::distance(__first, __last));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator, class _Sentinel>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<bool, _Allocator>::iterator
|
|
|
|
vector<bool, _Allocator>::__insert_with_size(
|
|
|
|
const_iterator __position, _ForwardIterator __first, _Sentinel __last, difference_type __n_signed) {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__n_signed >= 0, "invalid range specified");
|
2016-12-11 05:31:00 +00:00
|
|
|
const size_type __n = static_cast<size_type>(__n_signed);
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __r;
|
|
|
|
size_type __c = capacity();
|
|
|
|
if (__n <= __c && size() <= __c - __n) {
|
|
|
|
const_iterator __old_end = end();
|
|
|
|
__size_ += __n;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy_backward(__position, __old_end, end());
|
2010-05-11 19:42:16 +00:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
} else {
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2022-07-31 17:53:10 +02:00
|
|
|
__r = std::copy(cbegin(), __position, __v.begin());
|
|
|
|
std::copy_backward(__position, cend(), __v.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__v);
|
|
|
|
}
|
2023-05-08 23:40:21 -07:00
|
|
|
std::__copy<_ClassicAlgPolicy>(__first, __last, __r);
|
2010-05-11 19:42:16 +00:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
2010-05-11 19:42:16 +00:00
|
|
|
vector<bool, _Allocator>::erase(const_iterator __position) {
|
|
|
|
iterator __r = __const_iterator_cast(__position);
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy(__position + 1, this->cend(), __r);
|
2010-05-11 19:42:16 +00:00
|
|
|
--__size_;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::iterator
|
|
|
|
vector<bool, _Allocator>::erase(const_iterator __first, const_iterator __last) {
|
|
|
|
iterator __r = __const_iterator_cast(__first);
|
|
|
|
difference_type __d = __last - __first;
|
2022-07-31 17:53:10 +02:00
|
|
|
std::copy(__last, this->cend(), __r);
|
2010-05-11 19:42:16 +00:00
|
|
|
__size_ -= __d;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::swap(vector& __x)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
|
|
_NOEXCEPT
|
|
|
|
#else
|
2016-12-28 06:06:09 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value)
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
{
|
2022-07-31 17:53:10 +02:00
|
|
|
std::swap(this->__begin_, __x.__begin_);
|
|
|
|
std::swap(this->__size_, __x.__size_);
|
|
|
|
std::swap(this->__cap(), __x.__cap());
|
|
|
|
std::__swap_allocator(
|
2015-07-13 20:04:56 +00:00
|
|
|
this->__alloc(), __x.__alloc(), integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::resize(size_type __sz, value_type __x) {
|
|
|
|
size_type __cs = size();
|
|
|
|
if (__cs < __sz) {
|
|
|
|
iterator __r;
|
|
|
|
size_type __c = capacity();
|
|
|
|
size_type __n = __sz - __cs;
|
|
|
|
if (__n <= __c && __cs <= __c - __n) {
|
|
|
|
__r = end();
|
|
|
|
__size_ += __n;
|
|
|
|
} else {
|
2021-10-21 10:38:56 +01:00
|
|
|
vector __v(get_allocator());
|
2010-05-11 19:42:16 +00:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2022-07-31 17:53:10 +02:00
|
|
|
__r = std::copy(cbegin(), cend(), __v.begin());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__v);
|
|
|
|
}
|
2022-07-31 17:53:10 +02:00
|
|
|
std::fill_n(__r, __n, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
} else
|
|
|
|
__size_ = __sz;
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Allocator>
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::flip() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
// do middle whole words
|
|
|
|
size_type __n = __size_;
|
|
|
|
__storage_pointer __p = __begin_;
|
|
|
|
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
|
|
|
|
*__p = ~*__p;
|
|
|
|
// do last partial word
|
|
|
|
if (__n > 0) {
|
|
|
|
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
|
|
|
__storage_type __b = *__p & __m;
|
|
|
|
*__p &= ~__m;
|
|
|
|
*__p |= ~__b & __m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Allocator>
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<bool, _Allocator>::__invariants() const {
|
2013-06-27 19:35:32 +00:00
|
|
|
if (this->__begin_ == nullptr) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (this->__size_ != 0 || this->__cap() != 0)
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if (this->__cap() == 0)
|
|
|
|
return false;
|
|
|
|
if (this->__size_ > this->capacity())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Allocator>
|
2011-06-03 19:40:40 +00:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 size_t vector<bool, _Allocator>::__hash_code() const _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
size_t __h = 0;
|
|
|
|
// do middle whole words
|
|
|
|
size_type __n = __size_;
|
|
|
|
__storage_pointer __p = __begin_;
|
|
|
|
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
|
|
|
|
__h ^= *__p;
|
|
|
|
// do last partial word
|
|
|
|
if (__n > 0) {
|
|
|
|
const __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
|
|
|
__h ^= *__p & __m;
|
|
|
|
}
|
|
|
|
return __h;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2017-01-04 23:56:00 +00:00
|
|
|
struct _LIBCPP_TEMPLATE_VIS hash<vector<bool, _Allocator> >
|
2022-06-22 10:11:14 +02:00
|
|
|
: public __unary_function<vector<bool, _Allocator>, size_t> {
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_t
|
2011-06-03 19:40:40 +00:00
|
|
|
operator()(const vector<bool, _Allocator>& __vec) const _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return __vec.__hash_code();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool
|
2010-05-11 19:42:16 +00:00
|
|
|
operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
const typename vector<_Tp, _Allocator>::size_type __sz = __x.size();
|
2022-07-31 17:53:10 +02:00
|
|
|
return __sz == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2023-05-20 18:37:00 +03:00
|
|
|
#if _LIBCPP_STD_VER <= 17
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
2022-07-31 17:53:10 +02:00
|
|
|
return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
return __y < __x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
return !(__x < __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
return !(__y < __x);
|
|
|
|
}
|
|
|
|
|
2023-05-20 18:37:00 +03:00
|
|
|
#else // _LIBCPP_STD_VER <= 17
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
|
|
|
|
operator<=>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
|
|
|
|
return std::lexicographical_compare_three_way(
|
|
|
|
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // _LIBCPP_STD_VER <= 17
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
|
|
|
|
__x.swap(__y);
|
|
|
|
}
|
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 20
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class _Tp, class _Allocator, class _Up>
|
2022-07-31 17:53:10 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type
|
2020-05-02 13:58:03 +02:00
|
|
|
erase(vector<_Tp, _Allocator>& __c, const _Up& __v) {
|
|
|
|
auto __old_size = __c.size();
|
2022-07-31 17:53:10 +02:00
|
|
|
__c.erase(std::remove(__c.begin(), __c.end(), __v), __c.end());
|
2020-05-02 13:58:03 +02:00
|
|
|
return __old_size - __c.size();
|
|
|
|
}
|
2018-12-14 18:49:35 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator, class _Predicate>
|
2022-07-31 17:53:10 +02:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type
|
2020-05-02 13:58:03 +02:00
|
|
|
erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) {
|
|
|
|
auto __old_size = __c.size();
|
2022-07-31 17:53:10 +02:00
|
|
|
__c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
|
2020-05-02 13:58:03 +02:00
|
|
|
return __old_size - __c.size();
|
|
|
|
}
|
2021-09-26 15:47:42 +02:00
|
|
|
|
|
|
|
template <>
|
2023-01-14 16:46:15 +01:00
|
|
|
inline constexpr bool __format::__enable_insertable<vector<char>> = true;
|
2021-09-26 15:47:42 +02:00
|
|
|
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
|
|
|
template <>
|
2023-01-14 16:46:15 +01:00
|
|
|
inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
|
2018-12-14 18:49:35 +00:00
|
|
|
# endif
|
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#endif // _LIBCPP_STD_VER >= 20
|
2021-09-26 15:47:42 +02:00
|
|
|
|
2023-05-17 19:17:52 +02:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
2023-07-24 19:53:39 -07:00
|
|
|
template <class _Tp, class _CharT>
|
2022-11-29 07:57:30 +01:00
|
|
|
// Since is-vector-bool-reference is only used once it's inlined here.
|
|
|
|
requires same_as<typename _Tp::__container, vector<bool, typename _Tp::__container::allocator_type>>
|
2023-07-24 19:53:39 -07:00
|
|
|
struct _LIBCPP_TEMPLATE_VIS formatter<_Tp, _CharT> {
|
2022-11-29 07:57:30 +01:00
|
|
|
private:
|
2023-07-24 19:53:39 -07:00
|
|
|
formatter<bool, _CharT> __underlying_;
|
2022-11-29 07:57:30 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
template <class _ParseContext>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
|
|
|
|
return __underlying_.parse(__ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _FormatContext>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __ref, _FormatContext& __ctx) const {
|
|
|
|
return __underlying_.format(__ref, __ctx);
|
|
|
|
}
|
|
|
|
};
|
2023-05-17 19:17:52 +02:00
|
|
|
#endif // _LIBCPP_STD_VER >= 23
|
2022-11-29 07:57:30 +01:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
2023-02-14 00:56:09 +01:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2022-10-06 16:53:30 -04:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
namespace pmr {
|
|
|
|
template <class _ValueT>
|
2023-03-29 16:48:20 -04:00
|
|
|
using vector _LIBCPP_AVAILABILITY_PMR = std::vector<_ValueT, polymorphic_allocator<_ValueT>>;
|
2022-10-06 16:53:30 -04:00
|
|
|
} // namespace pmr
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif
|
|
|
|
|
2017-05-31 22:07:49 +00:00
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
|
2022-09-02 17:53:28 +02:00
|
|
|
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
|
|
|
|
# include <algorithm>
|
2022-09-22 21:53:13 +02:00
|
|
|
# include <atomic>
|
2022-11-02 20:27:42 +01:00
|
|
|
# include <concepts>
|
2023-01-08 16:47:53 +01:00
|
|
|
# include <cstdlib>
|
2023-02-12 12:32:36 +01:00
|
|
|
# include <type_traits>
|
2022-09-02 17:53:28 +02:00
|
|
|
# include <typeinfo>
|
|
|
|
# include <utility>
|
|
|
|
#endif
|
|
|
|
|
2021-04-20 12:03:32 -04:00
|
|
|
#endif // _LIBCPP_VECTOR
|