2010-05-12 03:42:16 +08:00
|
|
|
// -*- C++ -*-
|
2021-11-18 05:25:01 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-05-12 03:42:16 +08:00
|
|
|
//
|
2019-01-19 18:56:40 +08: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-12 03:42:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_VECTOR
|
|
|
|
#define _LIBCPP_VECTOR
|
|
|
|
|
|
|
|
/*
|
|
|
|
vector synopsis
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class T, class Allocator = allocator<T> >
|
2010-05-12 03:42:16 +08:00
|
|
|
class vector
|
2010-08-22 08:02:43 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef T value_type;
|
2010-05-12 03:42:16 +08: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-04 03:40:40 +08:00
|
|
|
vector()
|
|
|
|
noexcept(is_nothrow_default_constructible<allocator_type>::value);
|
|
|
|
explicit vector(const allocator_type&);
|
2010-05-12 03:42:16 +08:00
|
|
|
explicit vector(size_type n);
|
2013-09-14 08:47:59 +08:00
|
|
|
explicit vector(size_type n, const allocator_type&); // C++14
|
2010-05-12 03:42:16 +08: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());
|
|
|
|
vector(const vector& x);
|
2011-06-04 03:40:40 +08:00
|
|
|
vector(vector&& x)
|
|
|
|
noexcept(is_nothrow_move_constructible<allocator_type>::value);
|
2010-05-12 03:42:16 +08: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-04 03:40:40 +08:00
|
|
|
vector& operator=(vector&& x)
|
|
|
|
noexcept(
|
2015-08-19 02:57:00 +08:00
|
|
|
allocator_type::propagate_on_container_move_assignment::value ||
|
|
|
|
allocator_type::is_always_equal::value); // C++17
|
2010-05-12 03:42:16 +08:00
|
|
|
vector& operator=(initializer_list<value_type> il);
|
|
|
|
template <class InputIterator>
|
|
|
|
void assign(InputIterator first, InputIterator last);
|
|
|
|
void assign(size_type n, const value_type& u);
|
|
|
|
void assign(initializer_list<value_type> il);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
allocator_type get_allocator() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
iterator begin() noexcept;
|
|
|
|
const_iterator begin() const noexcept;
|
|
|
|
iterator end() noexcept;
|
|
|
|
const_iterator end() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
reverse_iterator rbegin() noexcept;
|
|
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
|
|
reverse_iterator rend() noexcept;
|
|
|
|
const_reverse_iterator rend() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08: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-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
size_type size() const noexcept;
|
|
|
|
size_type max_size() const noexcept;
|
|
|
|
size_type capacity() const noexcept;
|
|
|
|
bool empty() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
void reserve(size_type n);
|
2011-06-04 03:40:40 +08:00
|
|
|
void shrink_to_fit() noexcept;
|
2010-05-12 03:42:16 +08: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-04 03:40:40 +08:00
|
|
|
value_type* data() noexcept;
|
|
|
|
const value_type* data() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
void push_back(const value_type& x);
|
|
|
|
void push_back(value_type&& x);
|
|
|
|
template <class... Args>
|
2017-01-25 07:09:12 +08:00
|
|
|
reference emplace_back(Args&&... args); // reference in C++17
|
2010-05-12 03:42:16 +08: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);
|
|
|
|
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-04 03:40:40 +08:00
|
|
|
void clear() noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
void resize(size_type sz);
|
|
|
|
void resize(size_type sz, const value_type& c);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
void swap(vector&)
|
2015-07-14 04:04:56 +08:00
|
|
|
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
|
|
|
|
allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
bool __invariants() const;
|
2010-08-22 08:02:43 +08:00
|
|
|
};
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class Allocator = allocator<T> >
|
2010-05-12 03:42:16 +08:00
|
|
|
class vector<bool, Allocator>
|
2010-08-22 08:02:43 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef bool value_type;
|
2010-05-12 03:42:16 +08: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-04 03:40:40 +08:00
|
|
|
reference(const reference&) noexcept;
|
|
|
|
operator bool() const noexcept;
|
2021-06-30 01:52:26 +08:00
|
|
|
reference& operator=(bool x) noexcept;
|
2011-06-04 03:40:40 +08:00
|
|
|
reference& operator=(const reference& x) noexcept;
|
|
|
|
iterator operator&() const noexcept;
|
|
|
|
void flip() noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class const_reference
|
|
|
|
{
|
|
|
|
public:
|
2011-06-04 03:40:40 +08:00
|
|
|
const_reference(const reference&) noexcept;
|
|
|
|
operator bool() const noexcept;
|
|
|
|
const_iterator operator&() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
};
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
vector()
|
|
|
|
noexcept(is_nothrow_default_constructible<allocator_type>::value);
|
2011-09-03 04:42:31 +08:00
|
|
|
explicit vector(const allocator_type&);
|
2013-09-14 08:47:59 +08: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-12 03:42:16 +08:00
|
|
|
template <class InputIterator>
|
|
|
|
vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type());
|
|
|
|
vector(const vector& x);
|
2011-06-04 03:40:40 +08:00
|
|
|
vector(vector&& x)
|
|
|
|
noexcept(is_nothrow_move_constructible<allocator_type>::value);
|
2010-05-12 03:42:16 +08: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-04 03:40:40 +08:00
|
|
|
vector& operator=(vector&& x)
|
|
|
|
noexcept(
|
2015-08-19 02:57:00 +08:00
|
|
|
allocator_type::propagate_on_container_move_assignment::value ||
|
|
|
|
allocator_type::is_always_equal::value); // C++17
|
2010-05-12 03:42:16 +08:00
|
|
|
vector& operator=(initializer_list<value_type> il);
|
|
|
|
template <class InputIterator>
|
|
|
|
void assign(InputIterator first, InputIterator last);
|
|
|
|
void assign(size_type n, const value_type& u);
|
|
|
|
void assign(initializer_list<value_type> il);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
allocator_type get_allocator() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
iterator begin() noexcept;
|
|
|
|
const_iterator begin() const noexcept;
|
|
|
|
iterator end() noexcept;
|
|
|
|
const_iterator end() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
reverse_iterator rbegin() noexcept;
|
|
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
|
|
reverse_iterator rend() noexcept;
|
|
|
|
const_reverse_iterator rend() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08: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-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
size_type size() const noexcept;
|
|
|
|
size_type max_size() const noexcept;
|
|
|
|
size_type capacity() const noexcept;
|
|
|
|
bool empty() const noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
void reserve(size_type n);
|
2011-06-04 03:40:40 +08:00
|
|
|
void shrink_to_fit() noexcept;
|
2010-05-12 03:42:16 +08: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-25 07:09:12 +08:00
|
|
|
template <class... Args> reference emplace_back(Args&&... args); // C++14; reference in C++17
|
2010-05-12 03:42:16 +08:00
|
|
|
void pop_back();
|
|
|
|
|
2013-08-14 07:54:12 +08:00
|
|
|
template <class... Args> iterator emplace(const_iterator position, Args&&... args); // C++14
|
2010-05-12 03:42:16 +08: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);
|
|
|
|
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-04 03:40:40 +08:00
|
|
|
void clear() noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
void resize(size_type sz);
|
|
|
|
void resize(size_type sz, value_type x);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
void swap(vector&)
|
2015-07-14 04:04:56 +08:00
|
|
|
noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
|
|
|
|
allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
2011-06-04 03:40:40 +08:00
|
|
|
void flip() noexcept;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
bool __invariants() const;
|
2010-08-22 08:02:43 +08:00
|
|
|
};
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2018-05-22 05:30:12 +08:00
|
|
|
template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
|
|
|
|
vector(InputIterator, InputIterator, Allocator = Allocator())
|
2021-11-10 01:21:02 +08:00
|
|
|
-> vector<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17
|
2018-05-22 05:30:12 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class Allocator> struct hash<std::vector<bool, Allocator>>;
|
|
|
|
|
|
|
|
template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
template <class T, class Allocator>
|
|
|
|
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
|
|
|
|
noexcept(noexcept(x.swap(y)));
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2018-12-15 02:49:35 +08:00
|
|
|
template <class T, class Allocator, class U>
|
2020-05-02 19:58:03 +08:00
|
|
|
typename vector<T, Allocator>::size_type
|
|
|
|
erase(vector<T, Allocator>& c, const U& value); // C++20
|
2018-12-15 02:49:35 +08:00
|
|
|
template <class T, class Allocator, class Predicate>
|
2020-05-02 19:58:03 +08:00
|
|
|
typename vector<T, Allocator>::size_type
|
|
|
|
erase_if(vector<T, Allocator>& c, Predicate pred); // C++20
|
2018-12-15 02:49:35 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
} // std
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <__bit_reference>
|
2022-01-07 22:45:05 +08:00
|
|
|
#include <__config>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <__debug>
|
2021-11-10 01:21:02 +08:00
|
|
|
#include <__iterator/iterator_traits.h>
|
2021-06-11 21:55:11 +08:00
|
|
|
#include <__iterator/wrap_iter.h>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <__split_buffer>
|
2021-06-05 10:47:47 +08:00
|
|
|
#include <__utility/forward.h>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <algorithm>
|
2010-05-12 03:42:16 +08:00
|
|
|
#include <climits>
|
2021-03-25 06:19:12 +08:00
|
|
|
#include <compare>
|
2021-08-20 00:39:16 +08:00
|
|
|
#include <cstdlib>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <cstring>
|
2010-05-12 03:42:16 +08:00
|
|
|
#include <initializer_list>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <iosfwd> // for forward declaration of vector
|
|
|
|
#include <limits>
|
2010-05-12 03:42:16 +08:00
|
|
|
#include <memory>
|
|
|
|
#include <stdexcept>
|
2021-05-19 23:57:04 +08:00
|
|
|
#include <type_traits>
|
2018-09-13 03:41:40 +08: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 08:26:35 +08:00
|
|
|
|
2022-02-12 02:15:18 +08:00
|
|
|
// TODO: remove these headers
|
|
|
|
#include <__functional/binary_function.h>
|
|
|
|
#include <__functional/invoke.h>
|
|
|
|
#include <__functional/operations.h>
|
|
|
|
#include <__functional/reference_wrapper.h>
|
|
|
|
#include <__functional/unary_function.h>
|
|
|
|
#include <__functional/weak_result_type.h>
|
|
|
|
#include <typeinfo>
|
|
|
|
#include <utility>
|
|
|
|
|
2011-10-18 04:05:10 +08:00
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
2022-02-02 09:16:40 +08:00
|
|
|
# pragma GCC system_header
|
2011-10-18 04:05:10 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2017-06-01 06:07:49 +08:00
|
|
|
_LIBCPP_PUSH_MACROS
|
|
|
|
#include <__undef_macros>
|
|
|
|
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
2016-02-20 08:19:45 +08:00
|
|
|
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
|
2017-01-05 07:56:00 +08:00
|
|
|
class _LIBCPP_TEMPLATE_VIS vector
|
2010-05-12 03:42:16 +08: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-02 03:55:46 +08:00
|
|
|
typedef allocator<_Tp> __default_allocator_type;
|
2010-08-22 08:02:43 +08: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-02 03: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;
|
|
|
|
typedef __wrap_iter<pointer> iterator;
|
|
|
|
typedef __wrap_iter<const_pointer> const_iterator;
|
|
|
|
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2013-03-27 03:04:56 +08:00
|
|
|
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
|
|
|
"Allocator::value_type must be same type as value_type");
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2015-06-04 10:05:41 +08:00
|
|
|
vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
|
2022-01-11 07:33:35 +08:00
|
|
|
{
|
|
|
|
_VSTD::__debug_db_insert_c(this);
|
|
|
|
}
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a)
|
2015-06-04 08:10:20 +08:00
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
|
|
|
|
#else
|
|
|
|
_NOEXCEPT
|
|
|
|
#endif
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2011-09-15 02:33:51 +08:00
|
|
|
}
|
2010-05-12 03:42:16 +08:00
|
|
|
explicit vector(size_type __n);
|
2013-09-14 08:47:59 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
explicit vector(size_type __n, const allocator_type& __a);
|
|
|
|
#endif
|
2018-05-22 05:30:12 +08:00
|
|
|
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-02 03:55:46 +08:00
|
|
|
|
|
|
|
template <class = __enable_if_t<__is_allocator<_Allocator>::value> >
|
|
|
|
vector(size_type __n, const value_type& __x, const allocator_type& __a)
|
2022-02-04 06:09:37 +08: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-02 03:55:46 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
[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-02 03:55:46 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
|
|
|
__vallocate(__n);
|
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _InputIterator>
|
2013-09-22 05:13:54 +08:00
|
|
|
vector(_InputIterator __first,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
2013-09-22 05:13:54 +08:00
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
_InputIterator>::type __last);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _InputIterator>
|
|
|
|
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value>::type* = 0);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _ForwardIterator>
|
2013-09-22 05:13:54 +08:00
|
|
|
vector(_ForwardIterator __first,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
2013-09-22 05:13:54 +08:00
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
_ForwardIterator>::type __last);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-09-15 02:33:51 +08:00
|
|
|
~vector()
|
|
|
|
{
|
2021-11-08 16:10:13 +08:00
|
|
|
__annotate_delete();
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2021-11-08 16:10:13 +08:00
|
|
|
__get_db()->__erase_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
#endif
|
2021-11-08 16:10:13 +08:00
|
|
|
|
|
|
|
if (this->__begin_ != nullptr)
|
|
|
|
{
|
|
|
|
__clear();
|
|
|
|
__alloc_traits::deallocate(__alloc(), this->__begin_, capacity());
|
|
|
|
}
|
2018-09-07 23:47:59 +08:00
|
|
|
}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
vector(const vector& __x);
|
2021-03-02 06:08:24 +08:00
|
|
|
vector(const vector& __x, const __identity_t<allocator_type>& __a);
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector& operator=(const vector& __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
vector(initializer_list<value_type> __il);
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
vector(vector&& __x)
|
2015-07-14 22:46:32 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
|
|
|
_NOEXCEPT;
|
|
|
|
#else
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
2015-07-14 22:46:32 +08:00
|
|
|
#endif
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2021-03-02 06:08:24 +08:00
|
|
|
vector(vector&& __x, const __identity_t<allocator_type>& __a);
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
vector& operator=(vector&& __x)
|
2015-08-19 02:57:00 +08:00
|
|
|
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector& operator=(initializer_list<value_type> __il)
|
|
|
|
{assign(__il.begin(), __il.end()); return *this;}
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
assign(_InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
assign(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
|
|
|
|
void assign(size_type __n, const_reference __u);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void assign(initializer_list<value_type> __il)
|
|
|
|
{assign(__il.begin(), __il.end());}
|
2017-04-16 10:40:45 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
allocator_type get_allocator() const _NOEXCEPT
|
|
|
|
{return this->__alloc();}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
reverse_iterator rbegin() _NOEXCEPT
|
|
|
|
{return reverse_iterator(end());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator rbegin() const _NOEXCEPT
|
|
|
|
{return const_reverse_iterator(end());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
reverse_iterator rend() _NOEXCEPT
|
|
|
|
{return reverse_iterator(begin());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator rend() const _NOEXCEPT
|
|
|
|
{return const_reverse_iterator(begin());}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator cbegin() const _NOEXCEPT
|
|
|
|
{return begin();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator cend() const _NOEXCEPT
|
|
|
|
{return end();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator crbegin() const _NOEXCEPT
|
|
|
|
{return rbegin();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator crend() const _NOEXCEPT
|
|
|
|
{return rend();}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
size_type size() const _NOEXCEPT
|
|
|
|
{return static_cast<size_type>(this->__end_ - this->__begin_);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
size_type capacity() const _NOEXCEPT
|
2021-11-08 16:10:13 +08:00
|
|
|
{return static_cast<size_type>(__end_cap() - this->__begin_);}
|
2017-11-15 13:51:26 +08:00
|
|
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
bool empty() const _NOEXCEPT
|
|
|
|
{return this->__begin_ == this->__end_;}
|
|
|
|
size_type max_size() const _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
void reserve(size_type __n);
|
2011-06-04 03:40:40 +08:00
|
|
|
void shrink_to_fit() _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2019-03-15 08:29:35 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
reference at(size_type __n);
|
|
|
|
const_reference at(size_type __n) const;
|
|
|
|
|
2019-03-15 08:29:35 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2021-05-10 01:29:56 +08:00
|
|
|
_LIBCPP_ASSERT(!empty(), "front() called on an empty vector");
|
2011-09-15 02:33:51 +08:00
|
|
|
return *this->__begin_;
|
|
|
|
}
|
2019-03-15 08:29:35 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2021-05-10 01:29:56 +08:00
|
|
|
_LIBCPP_ASSERT(!empty(), "front() called on an empty vector");
|
2011-09-15 02:33:51 +08:00
|
|
|
return *this->__begin_;
|
|
|
|
}
|
2019-03-15 08:29:35 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2021-05-10 01:29:56 +08:00
|
|
|
_LIBCPP_ASSERT(!empty(), "back() called on an empty vector");
|
2011-09-15 02:33:51 +08:00
|
|
|
return *(this->__end_ - 1);
|
|
|
|
}
|
2019-03-15 08:29:35 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2021-05-10 01:29:56 +08:00
|
|
|
_LIBCPP_ASSERT(!empty(), "back() called on an empty vector");
|
2011-09-15 02:33:51 +08:00
|
|
|
return *(this->__end_ - 1);
|
|
|
|
}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
value_type* data() _NOEXCEPT
|
2019-11-17 06:13:26 +08:00
|
|
|
{return _VSTD::__to_address(this->__begin_);}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const value_type* data() const _NOEXCEPT
|
2019-11-17 06:13:26 +08:00
|
|
|
{return _VSTD::__to_address(this->__begin_);}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2017-10-17 21:03:17 +08:00
|
|
|
#ifdef _LIBCPP_CXX03_LANG
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __emplace_back(const value_type& __x) { push_back(__x); }
|
|
|
|
#else
|
|
|
|
template <class _Arg>
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __emplace_back(_Arg&& __arg) {
|
|
|
|
emplace_back(_VSTD::forward<_Arg>(__arg));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2012-02-15 08:41:34 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class... _Args>
|
2015-11-07 09:22:13 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2017-01-25 07:09:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
2016-07-21 11:20:17 +08:00
|
|
|
reference emplace_back(_Args&&... __args);
|
2017-01-25 07:09:12 +08:00
|
|
|
#else
|
|
|
|
void emplace_back(_Args&&... __args);
|
|
|
|
#endif
|
2017-04-16 10:40:45 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
|
|
|
|
2015-11-07 09:22:13 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void pop_back();
|
|
|
|
|
|
|
|
iterator insert(const_iterator __position, const_reference __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator insert(const_iterator __position, value_type&& __x);
|
|
|
|
template <class... _Args>
|
|
|
|
iterator emplace(const_iterator __position, _Args&&... __args);
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator insert(const_iterator __position, size_type __n, const_reference __x);
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator
|
|
|
|
>::type
|
|
|
|
insert(const_iterator __position, _InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator
|
|
|
|
>::type
|
|
|
|
insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator insert(const_iterator __position, initializer_list<value_type> __il)
|
|
|
|
{return insert(__position, __il.begin(), __il.end());}
|
2017-04-16 10:40:45 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position);
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator erase(const_iterator __first, const_iterator __last);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void clear() _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2014-05-08 22:14:06 +08:00
|
|
|
size_type __old_size = size();
|
2021-11-08 16:10:13 +08:00
|
|
|
__clear();
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_shrink(__old_size);
|
2011-09-15 02:33:51 +08:00
|
|
|
__invalidate_all_iterators();
|
|
|
|
}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
void resize(size_type __sz);
|
|
|
|
void resize(size_type __sz, const_reference __x);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
void swap(vector&)
|
2015-07-14 04:04:56 +08: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-19 05:50:12 +08:00
|
|
|
_NOEXCEPT;
|
2015-07-14 04:04:56 +08: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-19 05:50:12 +08:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
2015-07-14 04:04:56 +08:00
|
|
|
__is_nothrow_swappable<allocator_type>::value);
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
bool __invariants() const;
|
|
|
|
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2011-09-15 02:33:51 +08:00
|
|
|
|
|
|
|
bool __dereferenceable(const const_iterator* __i) const;
|
|
|
|
bool __decrementable(const const_iterator* __i) const;
|
|
|
|
bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
|
|
|
|
bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_DEBUG_LEVEL == 2
|
2011-09-15 02:33:51 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
private:
|
2022-02-04 06:09:37 +08:00
|
|
|
pointer __begin_ = nullptr;
|
|
|
|
pointer __end_ = nullptr;
|
|
|
|
__compressed_pair<pointer, allocator_type> __end_cap_ =
|
|
|
|
__compressed_pair<pointer, allocator_type>(nullptr, __default_init_tag());
|
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
|
2016-12-28 14:06:09 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(pointer __new_last);
|
2018-05-23 00:20:28 +08:00
|
|
|
void __vallocate(size_type __n);
|
|
|
|
void __vdeallocate() _NOEXCEPT;
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const;
|
2011-01-05 03:53:31 +08:00
|
|
|
void __construct_at_end(size_type __n);
|
2015-11-07 09:22:13 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void __construct_at_end(size_type __n, const_reference __x);
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
[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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
void __append(size_type __n);
|
|
|
|
void __append(size_type __n, const_reference __x);
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
iterator __make_iter(pointer __p) _NOEXCEPT;
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
const_iterator __make_iter(const_pointer __p) const _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
void __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v);
|
|
|
|
pointer __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p);
|
|
|
|
void __move_range(pointer __from_s, pointer __from_e, pointer __to);
|
2011-06-04 03:40:40 +08:00
|
|
|
void __move_assign(vector& __c, true_type)
|
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
2015-08-19 02:57:00 +08:00
|
|
|
void __move_assign(vector& __c, false_type)
|
|
|
|
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2013-06-28 03:35:32 +08:00
|
|
|
void __destruct_at_end(pointer __new_last) _NOEXCEPT
|
2011-09-15 02:33:51 +08:00
|
|
|
{
|
2016-12-28 14:06:09 +08:00
|
|
|
__invalidate_iterators_past(__new_last);
|
2014-05-08 22:14:06 +08:00
|
|
|
size_type __old_size = size();
|
2021-11-08 16:10:13 +08:00
|
|
|
__base_destruct_at_end(__new_last);
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_shrink(__old_size);
|
2011-09-15 02:33:51 +08:00
|
|
|
}
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2019-03-20 03:19:44 +08:00
|
|
|
template <class _Up>
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
inline void __push_back_slow_path(_Up&& __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2012-02-26 23:30:12 +08:00
|
|
|
template <class... _Args>
|
2019-03-20 03:19:44 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
inline void __emplace_back_slow_path(_Args&&... __args);
|
2017-04-16 10:40:45 +08:00
|
|
|
#else
|
2019-03-20 03:19:44 +08:00
|
|
|
template <class _Up>
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
inline void __push_back_slow_path(_Up& __x);
|
2012-02-26 23:30:12 +08:00
|
|
|
#endif
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2014-05-08 22:14:06 +08:00
|
|
|
// The following functions are no-ops outside of AddressSanitizer mode.
|
|
|
|
// We call annotatations only for the default Allocator because other allocators
|
|
|
|
// may not meet the AddressSanitizer alignment constraints.
|
|
|
|
// See the documentation for __sanitizer_annotate_contiguous_container for more details.
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2016-12-24 07:37:52 +08:00
|
|
|
void __annotate_contiguous_container(const void *__beg, const void *__end,
|
|
|
|
const void *__old_mid,
|
|
|
|
const void *__new_mid) const
|
|
|
|
{
|
|
|
|
|
2014-05-08 22:14:06 +08:00
|
|
|
if (__beg && is_same<allocator_type, __default_allocator_type>::value)
|
|
|
|
__sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid);
|
|
|
|
}
|
2016-12-24 07:37:52 +08:00
|
|
|
#else
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __annotate_contiguous_container(const void*, const void*, const void*,
|
2019-07-28 12:37:02 +08:00
|
|
|
const void*) const _NOEXCEPT {}
|
2016-12-24 07:37:52 +08:00
|
|
|
#endif
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2019-07-28 12:37:02 +08:00
|
|
|
void __annotate_new(size_type __current_size) const _NOEXCEPT {
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_contiguous_container(data(), data() + capacity(),
|
|
|
|
data() + capacity(), data() + __current_size);
|
|
|
|
}
|
2016-12-24 07:37:52 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2019-07-28 12:37:02 +08:00
|
|
|
void __annotate_delete() const _NOEXCEPT {
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_contiguous_container(data(), data() + capacity(),
|
|
|
|
data() + size(), data() + capacity());
|
|
|
|
}
|
2016-12-24 07:37:52 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2019-07-28 12:37:02 +08:00
|
|
|
void __annotate_increase(size_type __n) const _NOEXCEPT
|
2014-05-08 22:14:06 +08:00
|
|
|
{
|
|
|
|
__annotate_contiguous_container(data(), data() + capacity(),
|
|
|
|
data() + size(), data() + size() + __n);
|
|
|
|
}
|
2016-12-24 07:37:52 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2019-07-28 12:37:02 +08:00
|
|
|
void __annotate_shrink(size_type __old_size) const _NOEXCEPT
|
2014-05-08 22:14:06 +08:00
|
|
|
{
|
|
|
|
__annotate_contiguous_container(data(), data() + capacity(),
|
|
|
|
data() + __old_size, data() + size());
|
|
|
|
}
|
2019-07-28 12:37:02 +08:00
|
|
|
|
|
|
|
struct _ConstructTransaction {
|
|
|
|
explicit _ConstructTransaction(vector &__v, size_type __n)
|
2021-10-22 00:29:14 +08:00
|
|
|
: __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) {
|
2014-09-04 05:37:43 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
2019-07-28 12:37:02 +08:00
|
|
|
__v_.__annotate_increase(__n);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
~_ConstructTransaction() {
|
|
|
|
__v_.__end_ = __pos_;
|
|
|
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
|
|
|
if (__pos_ != __new_end_) {
|
|
|
|
__v_.__annotate_shrink(__new_end_ - __v_.__begin_);
|
2014-09-03 07:43:38 +08:00
|
|
|
}
|
2014-09-04 05:37:43 +08:00
|
|
|
#endif
|
2019-07-28 12:37:02 +08:00
|
|
|
}
|
2014-09-04 05:37:43 +08:00
|
|
|
|
2019-07-28 12:37:02 +08:00
|
|
|
vector &__v_;
|
|
|
|
pointer __pos_;
|
|
|
|
const_pointer const __new_end_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
_ConstructTransaction(_ConstructTransaction const&) = delete;
|
|
|
|
_ConstructTransaction& operator=(_ConstructTransaction const&) = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class ..._Args>
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __construct_one_at_end(_Args&& ...__args) {
|
|
|
|
_ConstructTransaction __tx(*this, 1);
|
2019-11-17 06:13:26 +08:00
|
|
|
__alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_),
|
2019-07-28 12:37:02 +08:00
|
|
|
_VSTD::forward<_Args>(__args)...);
|
|
|
|
++__tx.__pos_;
|
|
|
|
}
|
2021-11-08 16:10:13 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
allocator_type& __alloc() _NOEXCEPT
|
|
|
|
{return this->__end_cap_.second();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const allocator_type& __alloc() const _NOEXCEPT
|
|
|
|
{return this->__end_cap_.second();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
pointer& __end_cap() _NOEXCEPT
|
|
|
|
{return this->__end_cap_.first();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const pointer& __end_cap() const _NOEXCEPT
|
|
|
|
{return this->__end_cap_.first();}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __clear() _NOEXCEPT {__base_destruct_at_end(this->__begin_);}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
|
|
|
|
pointer __soon_to_be_end = this->__end_;
|
|
|
|
while (__new_last != __soon_to_be_end)
|
|
|
|
__alloc_traits::destroy(__alloc(), _VSTD::__to_address(--__soon_to_be_end));
|
|
|
|
this->__end_ = __new_last;
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __copy_assign_alloc(const vector& __c)
|
|
|
|
{__copy_assign_alloc(__c, integral_constant<bool,
|
|
|
|
__alloc_traits::propagate_on_container_copy_assignment::value>());}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
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>());}
|
|
|
|
|
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
|
|
|
|
void __throw_length_error() const {
|
2022-02-04 06:09:37 +08:00
|
|
|
_VSTD::__throw_length_error("vector");
|
2021-11-08 16:10:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
|
|
|
|
void __throw_out_of_range() const {
|
2022-02-04 06:09:37 +08:00
|
|
|
_VSTD::__throw_out_of_range("vector");
|
2021-11-08 16:10:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __copy_assign_alloc(const vector& __c, true_type)
|
|
|
|
{
|
|
|
|
if (__alloc() != __c.__alloc())
|
|
|
|
{
|
|
|
|
__clear();
|
|
|
|
__alloc_traits::deallocate(__alloc(), this->__begin_, capacity());
|
|
|
|
this->__begin_ = this->__end_ = __end_cap() = nullptr;
|
|
|
|
}
|
|
|
|
__alloc() = __c.__alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __copy_assign_alloc(const vector&, false_type)
|
|
|
|
{}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __move_assign_alloc(vector& __c, true_type)
|
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
|
|
|
{
|
|
|
|
__alloc() = _VSTD::move(__c.__alloc());
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void __move_assign_alloc(vector&, false_type)
|
|
|
|
_NOEXCEPT
|
|
|
|
{}
|
2010-05-12 03:42:16 +08:00
|
|
|
};
|
|
|
|
|
2021-08-17 23:59:07 +08:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2018-05-22 05:30:12 +08:00
|
|
|
template<class _InputIterator,
|
2021-03-04 12:02:20 +08:00
|
|
|
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
|
2021-11-10 01:21:02 +08:00
|
|
|
class = enable_if_t<__is_cpp17_input_iterator<_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-18 00:26:09 +08:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value>
|
2018-05-22 05:30:12 +08:00
|
|
|
>
|
|
|
|
vector(_InputIterator, _InputIterator)
|
2021-03-04 12:02:20 +08:00
|
|
|
-> vector<__iter_value_type<_InputIterator>, _Alloc>;
|
2018-05-22 05:30:12 +08:00
|
|
|
|
|
|
|
template<class _InputIterator,
|
|
|
|
class _Alloc,
|
2021-11-10 01:21:02 +08:00
|
|
|
class = enable_if_t<__is_cpp17_input_iterator<_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-18 00:26:09 +08:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value>
|
2018-05-22 05:30:12 +08:00
|
|
|
>
|
|
|
|
vector(_InputIterator, _InputIterator, _Alloc)
|
2021-03-04 12:02:20 +08:00
|
|
|
-> vector<__iter_value_type<_InputIterator>, _Alloc>;
|
2018-05-22 05:30:12 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
|
|
|
|
{
|
2019-09-14 00:09:33 +08:00
|
|
|
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_delete();
|
2020-11-19 07:54:38 +08:00
|
|
|
_VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::swap(this->__begin_, __v.__begin_);
|
|
|
|
_VSTD::swap(this->__end_, __v.__end_);
|
|
|
|
_VSTD::swap(this->__end_cap(), __v.__end_cap());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.__first_ = __v.__begin_;
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_new(size());
|
2010-05-12 03:42:16 +08:00
|
|
|
__invalidate_all_iterators();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::pointer
|
|
|
|
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p)
|
|
|
|
{
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_delete();
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __r = __v.__begin_;
|
2020-11-19 07:54:38 +08:00
|
|
|
_VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, __p, __v.__begin_);
|
|
|
|
_VSTD::__construct_forward_with_exception_guarantees(this->__alloc(), __p, this->__end_, __v.__end_);
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::swap(this->__begin_, __v.__begin_);
|
|
|
|
_VSTD::swap(this->__end_, __v.__end_);
|
|
|
|
_VSTD::swap(this->__end_cap(), __v.__end_cap());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.__first_ = __v.__begin_;
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_new(size());
|
2010-05-12 03:42:16 +08:00
|
|
|
__invalidate_all_iterators();
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
2018-05-23 00:20:28 +08:00
|
|
|
vector<_Tp, _Allocator>::__vallocate(size_type __n)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
|
|
|
this->__begin_ = this->__end_ = __alloc_traits::allocate(this->__alloc(), __n);
|
|
|
|
this->__end_cap() = this->__begin_ + __n;
|
2014-05-08 22:14:06 +08:00
|
|
|
__annotate_new(0);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
2018-05-23 00:20:28 +08:00
|
|
|
vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (this->__begin_ != nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
__alloc_traits::deallocate(this->__alloc(), this->__begin_, capacity());
|
2013-06-28 03:35:32 +08:00
|
|
|
this->__begin_ = this->__end_ = this->__end_cap() = nullptr;
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::size_type
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::max_size() const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2016-11-23 09:18:56 +08:00
|
|
|
return _VSTD::min<size_type>(__alloc_traits::max_size(this->__alloc()),
|
|
|
|
numeric_limits<difference_type>::max());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Precondition: __new_size > capacity()
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
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;
|
2021-07-27 06:23:00 +08:00
|
|
|
return _VSTD::max<size_type>(2 * __cap, __new_size);
|
2010-05-12 03:42:16 +08: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>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__construct_at_end(size_type __n)
|
|
|
|
{
|
2019-07-28 12:37:02 +08: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-19 01:14:02 +08:00
|
|
|
const_pointer __new_end = __tx.__new_end_;
|
2021-09-08 09:35:37 +08:00
|
|
|
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
|
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-19 01:14:02 +08:00
|
|
|
__alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__pos));
|
2019-07-28 12:37:02 +08:00
|
|
|
}
|
2010-05-12 03:42:16 +08: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>
|
2015-11-07 09:22:13 +08:00
|
|
|
inline
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
|
|
|
|
{
|
2019-07-28 12:37:02 +08: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-19 01:14:02 +08:00
|
|
|
const_pointer __new_end = __tx.__new_end_;
|
2021-09-08 09:35:37 +08:00
|
|
|
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
|
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-19 01:14:02 +08:00
|
|
|
__alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__pos), __x);
|
2019-07-28 12:37:02 +08:00
|
|
|
}
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
[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-04-01 00:54:19 +08:00
|
|
|
vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
_ConstructTransaction __tx(*this, __n);
|
2020-11-19 07:54:38 +08:00
|
|
|
_VSTD::__construct_range_forward(this->__alloc(), __first, __last, __tx.__pos_);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// throws if construction throws
|
|
|
|
// Postcondition: size() == size() + __n
|
2011-06-04 03:40:40 +08:00
|
|
|
// Exception safety: strong.
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
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-04 03:40:40 +08:00
|
|
|
// Exception safety: strong.
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
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>
|
|
|
|
vector<_Tp, _Allocator>::vector(size_type __n)
|
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-14 08:47:59 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2013-09-14 08:47:59 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2013-09-14 08:47:59 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2013-09-14 08:47:59 +08:00
|
|
|
__construct_at_end(__n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2018-05-22 05:30:12 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _InputIterator>
|
2013-09-22 05:13:54 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(_InputIterator __first,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
2013-09-22 05:13:54 +08:00
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
|
|
|
_InputIterator>::type __last)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2011-09-17 02:41:29 +08:00
|
|
|
for (; __first != __last; ++__first)
|
2017-10-17 21:03:17 +08:00
|
|
|
__emplace_back(*__first);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value>::type*)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2011-09-17 02:41:29 +08:00
|
|
|
for (; __first != __last; ++__first)
|
2017-10-17 21:03:17 +08:00
|
|
|
__emplace_back(*__first);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
2013-09-22 05:13:54 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(_ForwardIterator __first,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
2013-09-22 05:13:54 +08:00
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
|
|
|
_ForwardIterator>::type __last)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2011-07-01 05:18:19 +08:00
|
|
|
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__first, __last, __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
value_type,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value>::type*)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2011-07-01 05:18:19 +08:00
|
|
|
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__first, __last, __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
vector<_Tp, _Allocator>::vector(const vector& __x)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc()))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
size_type __n = __x.size();
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__x.__begin_, __x.__end_, __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2021-03-02 06:08:24 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(const vector& __x, const __identity_t<allocator_type>& __a)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
size_type __n = __x.size();
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__x.__begin_, __x.__end_, __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(vector&& __x)
|
2015-07-14 22:46:32 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
|
|
|
_NOEXCEPT
|
|
|
|
#else
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
2015-07-14 22:46:32 +08:00
|
|
|
#endif
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, _VSTD::move(__x.__alloc()))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2021-10-10 21:40:50 +08:00
|
|
|
__get_db()->swap(this, _VSTD::addressof(__x));
|
2011-09-15 02:33:51 +08:00
|
|
|
#endif
|
2011-09-17 02:41:29 +08:00
|
|
|
this->__begin_ = __x.__begin_;
|
|
|
|
this->__end_ = __x.__end_;
|
|
|
|
this->__end_cap() = __x.__end_cap();
|
2013-06-28 03:35:32 +08:00
|
|
|
__x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr;
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2021-03-02 06:08:24 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(vector&& __x, const __identity_t<allocator_type>& __a)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08: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;
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2021-10-10 21:40:50 +08:00
|
|
|
__get_db()->swap(this, _VSTD::addressof(__x));
|
2011-09-20 00:34:29 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-11-30 02:15:50 +08:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
assign(_Ip(__x.begin()), _Ip(__x.end()));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il)
|
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__il.size() > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08: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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __il.size());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
|
2022-02-04 06:09:37 +08:00
|
|
|
: __end_cap_(nullptr, __a)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2022-01-11 07:33:35 +08:00
|
|
|
_VSTD::__debug_db_insert_c(this);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__il.size() > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08: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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__il.begin(), __il.end(), __il.size());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>&
|
|
|
|
vector<_Tp, _Allocator>::operator=(vector&& __x)
|
2015-08-19 02:57:00 +08:00
|
|
|
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__move_assign(__x, integral_constant<bool,
|
|
|
|
__alloc_traits::propagate_on_container_move_assignment::value>());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
|
2015-08-19 02:57:00 +08:00
|
|
|
_NOEXCEPT_(__alloc_traits::is_always_equal::value)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2021-11-08 16:10:13 +08:00
|
|
|
if (__alloc() != __c.__alloc())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-11-30 02:15:50 +08:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
assign(_Ip(__c.begin()), _Ip(__c.end()));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
__move_assign(__c, true_type());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
2021-11-08 16:10:13 +08:00
|
|
|
__move_assign_alloc(__c); // this can throw
|
2010-05-12 03:42:16 +08:00
|
|
|
this->__begin_ = __c.__begin_;
|
|
|
|
this->__end_ = __c.__end_;
|
|
|
|
this->__end_cap() = __c.__end_cap();
|
|
|
|
__c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr;
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2021-10-10 21:40:50 +08:00
|
|
|
__get_db()->swap(this, _VSTD::addressof(__c));
|
2011-09-20 00:34:29 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>&
|
|
|
|
vector<_Tp, _Allocator>::operator=(const vector& __x)
|
|
|
|
{
|
2021-09-29 01:15:18 +08:00
|
|
|
if (this != _VSTD::addressof(__x))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2021-11-08 16:10:13 +08:00
|
|
|
__copy_assign_alloc(__x);
|
2010-05-12 03:42:16 +08:00
|
|
|
assign(__x.__begin_, __x.__end_);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
_Tp,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
for (; __first != __last; ++__first)
|
2017-10-17 21:03:17 +08:00
|
|
|
__emplace_back(*__first);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
_Tp,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
|
|
|
|
{
|
[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-04-01 00:54:19 +08:00
|
|
|
size_type __new_size = static_cast<size_type>(_VSTD::distance(__first, __last));
|
|
|
|
if (__new_size <= capacity())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
_ForwardIterator __mid = __last;
|
|
|
|
bool __growing = false;
|
[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-04-01 00:54:19 +08:00
|
|
|
if (__new_size > size())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__growing = true;
|
|
|
|
__mid = __first;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::advance(__mid, size());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
pointer __m = _VSTD::copy(__first, __mid, this->__begin_);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__growing)
|
[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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__mid, __last, __new_size - size());
|
2010-05-12 03:42:16 +08:00
|
|
|
else
|
|
|
|
this->__destruct_at_end(__m);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-23 00:20:28 +08: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-04-01 00:54:19 +08:00
|
|
|
__construct_at_end(__first, __last, __new_size);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2016-12-28 14:06:09 +08:00
|
|
|
__invalidate_all_iterators();
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u)
|
|
|
|
{
|
|
|
|
if (__n <= capacity())
|
|
|
|
{
|
|
|
|
size_type __s = size();
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(this->__begin_, _VSTD::min(__n, __s), __u);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > __s)
|
|
|
|
__construct_at_end(__n - __s, __u);
|
|
|
|
else
|
2010-05-25 01:49:41 +08:00
|
|
|
this->__destruct_at_end(this->__begin_ + __n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__recommend(static_cast<size_type>(__n)));
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n, __u);
|
|
|
|
}
|
2016-12-28 14:06:09 +08:00
|
|
|
__invalidate_all_iterators();
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::__make_iter(pointer __p) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2010-05-12 03:42:16 +08:00
|
|
|
return iterator(this, __p);
|
|
|
|
#else
|
|
|
|
return iterator(__p);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::const_iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::__make_iter(const_pointer __p) const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2010-05-12 03:42:16 +08:00
|
|
|
return const_iterator(this, __p);
|
|
|
|
#else
|
|
|
|
return const_iterator(__p);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::begin() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return __make_iter(this->__begin_);
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::const_iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::begin() const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return __make_iter(this->__begin_);
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::end() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return __make_iter(this->__end_);
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::const_iterator
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::end() const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return __make_iter(this->__end_);
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::reference
|
2019-03-15 08:29:35 +08:00
|
|
|
vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds");
|
2010-05-12 03:42:16 +08:00
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::const_reference
|
2019-03-15 08:29:35 +08:00
|
|
|
vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds");
|
2010-05-12 03:42:16 +08:00
|
|
|
return this->__begin_[__n];
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
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 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
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>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::reserve(size_type __n)
|
|
|
|
{
|
|
|
|
if (__n > capacity())
|
|
|
|
{
|
2021-10-21 17:40:05 +08:00
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
2010-05-12 03:42:16 +08:00
|
|
|
allocator_type& __a = this->__alloc();
|
2011-06-04 03:40:40 +08:00
|
|
|
__split_buffer<value_type, allocator_type&> __v(__n, size(), __a);
|
2010-05-12 03:42:16 +08:00
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (capacity() > size())
|
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
allocator_type& __a = this->__alloc();
|
2011-06-04 03:40:40 +08:00
|
|
|
__split_buffer<value_type, allocator_type&> __v(size(), size(), __a);
|
2010-05-12 03:42:16 +08:00
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2012-02-15 08:41:34 +08:00
|
|
|
template <class _Up>
|
|
|
|
void
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2012-02-15 08:41:34 +08:00
|
|
|
vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x)
|
|
|
|
#else
|
|
|
|
vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
|
|
|
// __v.push_back(_VSTD::forward<_Up>(__x));
|
2019-11-17 06:13:26 +08:00
|
|
|
__alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), _VSTD::forward<_Up>(__x));
|
2013-01-12 04:36:59 +08:00
|
|
|
__v.__end_++;
|
2012-02-15 08:41:34 +08:00
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::push_back(const_reference __x)
|
|
|
|
{
|
2012-02-15 08:41:34 +08:00
|
|
|
if (this->__end_ != this->__end_cap())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(__x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
2012-02-15 08:41:34 +08:00
|
|
|
__push_back_slow_path(__x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::push_back(value_type&& __x)
|
|
|
|
{
|
|
|
|
if (this->__end_ < this->__end_cap())
|
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(_VSTD::move(__x));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
2012-02-15 08:41:34 +08:00
|
|
|
__push_back_slow_path(_VSTD::move(__x));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
|
|
|
void
|
2012-02-26 23:30:12 +08: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);
|
|
|
|
// __v.emplace_back(_VSTD::forward<_Args>(__args)...);
|
2019-11-17 06:13:26 +08:00
|
|
|
__alloc_traits::construct(__a, _VSTD::__to_address(__v.__end_), _VSTD::forward<_Args>(__args)...);
|
2013-01-12 04:36:59 +08:00
|
|
|
__v.__end_++;
|
2012-02-26 23:30:12 +08:00
|
|
|
__swap_out_circular_buffer(__v);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
2015-11-07 09:22:13 +08:00
|
|
|
inline
|
2017-01-25 07:09:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
2016-07-21 11:20:17 +08:00
|
|
|
typename vector<_Tp, _Allocator>::reference
|
2017-01-25 07:09:12 +08:00
|
|
|
#else
|
|
|
|
void
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args)
|
|
|
|
{
|
|
|
|
if (this->__end_ < this->__end_cap())
|
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(_VSTD::forward<_Args>(__args)...);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
2012-02-26 23:30:12 +08:00
|
|
|
__emplace_back_slow_path(_VSTD::forward<_Args>(__args)...);
|
2017-01-25 07:09:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
2016-07-21 11:20:17 +08:00
|
|
|
return this->back();
|
2017-01-25 07:09:12 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2015-11-07 09:22:13 +08:00
|
|
|
inline
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::pop_back()
|
|
|
|
{
|
2021-05-10 01:29:56 +08:00
|
|
|
_LIBCPP_ASSERT(!empty(), "vector::pop_back called on an empty vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
this->__destruct_at_end(this->__end_ - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::erase(const_iterator __position)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::erase(iterator) called with an iterator not referring to this vector");
|
2013-03-26 06:12:26 +08:00
|
|
|
_LIBCPP_ASSERT(__position != end(),
|
|
|
|
"vector::erase(iterator) called with a non-dereferenceable iterator");
|
2013-06-28 03:35:32 +08:00
|
|
|
difference_type __ps = __position - cbegin();
|
|
|
|
pointer __p = this->__begin_ + __ps;
|
2011-07-01 05:18:19 +08:00
|
|
|
this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p));
|
2016-12-28 14:06:09 +08:00
|
|
|
this->__invalidate_iterators_past(__p-1);
|
|
|
|
iterator __r = __make_iter(__p);
|
2010-05-12 03:42:16 +08:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this,
|
|
|
|
"vector::erase(iterator, iterator) called with an iterator not referring to this vector");
|
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this,
|
|
|
|
"vector::erase(iterator, iterator) called with an iterator not referring to this vector");
|
|
|
|
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_ASSERT(__first <= __last, "vector::erase(first, last) called with invalid range");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__first - begin());
|
2016-12-28 14:06:09 +08:00
|
|
|
if (__first != __last) {
|
2013-04-18 23:02:57 +08:00
|
|
|
this->__destruct_at_end(_VSTD::move(__p + (__last - __first), this->__end_, __p));
|
2016-12-28 14:06:09 +08:00
|
|
|
this->__invalidate_iterators_past(__p - 1);
|
|
|
|
}
|
|
|
|
iterator __r = __make_iter(__p);
|
2010-05-12 03:42:16 +08:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
void
|
|
|
|
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 12:37:02 +08: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-19 01:14:02 +08:00
|
|
|
for (pointer __pos = __tx.__pos_; __i < __from_e;
|
2021-09-08 09:35:37 +08:00
|
|
|
++__i, (void) ++__pos, __tx.__pos_ = __pos) {
|
2019-07-28 12:37:02 +08:00
|
|
|
__alloc_traits::construct(this->__alloc(),
|
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-19 01:14:02 +08:00
|
|
|
_VSTD::__to_address(__pos),
|
2019-07-28 12:37:02 +08:00
|
|
|
_VSTD::move(*__i));
|
|
|
|
}
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::move_backward(__from_s, __from_s + __n, __old_last);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::insert(iterator, x) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (this->__end_ < this->__end_cap())
|
|
|
|
{
|
|
|
|
if (__p == this->__end_)
|
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(__x);
|
2010-05-12 03:42:16 +08: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
return __make_iter(__p);
|
|
|
|
}
|
|
|
|
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::insert(iterator, x) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (this->__end_ < this->__end_cap())
|
|
|
|
{
|
|
|
|
if (__p == this->__end_)
|
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(_VSTD::move(__x));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__move_range(__p, this->__end_, __p + 1);
|
2011-07-01 05:18:19 +08:00
|
|
|
*__p = _VSTD::move(__x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
|
2011-07-01 05:18:19 +08:00
|
|
|
__v.push_back(_VSTD::move(__x));
|
2010-05-12 03:42:16 +08:00
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
|
|
|
}
|
|
|
|
return __make_iter(__p);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class... _Args>
|
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::emplace(iterator, x) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (this->__end_ < this->__end_cap())
|
|
|
|
{
|
|
|
|
if (__p == this->__end_)
|
|
|
|
{
|
2019-07-28 12:37:02 +08:00
|
|
|
__construct_one_at_end(_VSTD::forward<_Args>(__args)...);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-07-12 05:38:08 +08:00
|
|
|
__temp_value<value_type, _Allocator> __tmp(this->__alloc(), _VSTD::forward<_Args>(__args)...);
|
2010-05-12 03:42:16 +08:00
|
|
|
__move_range(__p, this->__end_, __p + 1);
|
2016-07-12 05:38:08 +08:00
|
|
|
*__p = _VSTD::move(__tmp.get());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocator_type& __a = this->__alloc();
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, __a);
|
2011-07-01 05:18:19 +08:00
|
|
|
__v.emplace_back(_VSTD::forward<_Args>(__args)...);
|
2010-05-12 03:42:16 +08:00
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
|
|
|
}
|
|
|
|
return __make_iter(__p);
|
|
|
|
}
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::insert(iterator, n, x) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
|
|
|
if (__n <= static_cast<size_type>(this->__end_cap() - this->__end_))
|
|
|
|
{
|
|
|
|
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;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(__p, __n, *__xr);
|
2010-05-12 03:42:16 +08: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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return __make_iter(__p);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
_Tp,
|
|
|
|
typename iterator_traits<_InputIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
>::type
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::insert(iterator, range) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08: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 12:37:02 +08:00
|
|
|
__construct_one_at_end(*__first);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
__split_buffer<value_type, allocator_type&> __v(__a);
|
|
|
|
if (__first != __last)
|
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.__construct_at_end(__first, __last);
|
|
|
|
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;
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
erase(__make_iter(__old_last), end());
|
|
|
|
throw;
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
__p = _VSTD::rotate(__p, __old_last, this->__end_);
|
2020-02-11 17:59:12 +08:00
|
|
|
insert(__make_iter(__p), _VSTD::make_move_iterator(__v.begin()),
|
|
|
|
_VSTD::make_move_iterator(__v.end()));
|
2010-05-12 03:42:16 +08:00
|
|
|
return begin() + __off;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value &&
|
2013-03-29 01:44:32 +08:00
|
|
|
is_constructible<
|
|
|
|
_Tp,
|
|
|
|
typename iterator_traits<_ForwardIterator>::reference>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<_Tp, _Allocator>::iterator
|
|
|
|
>::type
|
|
|
|
vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last)
|
|
|
|
{
|
2022-01-16 03:23:29 +08:00
|
|
|
_LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
|
|
|
|
"vector::insert(iterator, range) called with an iterator not referring to this vector");
|
2010-05-12 03:42:16 +08:00
|
|
|
pointer __p = this->__begin_ + (__position - begin());
|
2011-07-01 05:18:19 +08:00
|
|
|
difference_type __n = _VSTD::distance(__first, __last);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
|
|
|
if (__n <= this->__end_cap() - this->__end_)
|
|
|
|
{
|
|
|
|
size_type __old_n = __n;
|
|
|
|
pointer __old_last = this->__end_;
|
|
|
|
_ForwardIterator __m = __last;
|
|
|
|
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-04-01 00:54:19 +08:00
|
|
|
difference_type __diff = this->__end_ - __p;
|
|
|
|
_VSTD::advance(__m, __diff);
|
|
|
|
__construct_at_end(__m, __last, __n - __diff);
|
2010-05-12 03:42:16 +08:00
|
|
|
__n = __dx;
|
|
|
|
}
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
|
|
|
__move_range(__p, __old_last, __p + __old_n);
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__first, __m, __p);
|
2010-05-12 03:42:16 +08: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(__first, __last);
|
|
|
|
__p = __swap_out_circular_buffer(__v, __p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return __make_iter(__p);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
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>
|
|
|
|
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>
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::swap(vector& __x)
|
2015-07-14 04:04:56 +08: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-19 05:50:12 +08:00
|
|
|
_NOEXCEPT
|
2015-07-14 04:04:56 +08: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-19 05:50:12 +08:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
2015-07-14 04:04:56 +08:00
|
|
|
__is_nothrow_swappable<allocator_type>::value)
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-09-15 02:33:51 +08:00
|
|
|
_LIBCPP_ASSERT(__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");
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::swap(this->__begin_, __x.__begin_);
|
|
|
|
_VSTD::swap(this->__end_, __x.__end_);
|
|
|
|
_VSTD::swap(this->__end_cap(), __x.__end_cap());
|
2020-11-19 07:54:38 +08:00
|
|
|
_VSTD::__swap_allocator(this->__alloc(), __x.__alloc(),
|
2015-07-14 04:04:56 +08:00
|
|
|
integral_constant<bool,__alloc_traits::propagate_on_container_swap::value>());
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2021-10-10 21:40:50 +08:00
|
|
|
__get_db()->swap(this, _VSTD::addressof(__x));
|
2020-10-03 03:02:52 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
vector<_Tp, _Allocator>::__invariants() const
|
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (this->__begin_ == nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (this->__end_ != nullptr || this->__end_cap() != nullptr)
|
2010-05-12 03:42:16 +08: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;
|
|
|
|
}
|
|
|
|
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2011-09-15 02:33:51 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
bool
|
|
|
|
vector<_Tp, _Allocator>::__dereferenceable(const const_iterator* __i) const
|
|
|
|
{
|
|
|
|
return this->__begin_ <= __i->base() && __i->base() < this->__end_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
bool
|
|
|
|
vector<_Tp, _Allocator>::__decrementable(const const_iterator* __i) const
|
|
|
|
{
|
|
|
|
return this->__begin_ < __i->base() && __i->base() <= this->__end_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
bool
|
|
|
|
vector<_Tp, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const
|
|
|
|
{
|
|
|
|
const_pointer __p = __i->base() + __n;
|
|
|
|
return this->__begin_ <= __p && __p <= this->__end_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
bool
|
|
|
|
vector<_Tp, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const
|
|
|
|
{
|
|
|
|
const_pointer __p = __i->base() + __n;
|
|
|
|
return this->__begin_ <= __p && __p < this->__end_;
|
|
|
|
}
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_DEBUG_LEVEL == 2
|
2011-09-15 02:33:51 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__invalidate_all_iterators()
|
|
|
|
{
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2011-09-15 02:33:51 +08:00
|
|
|
__get_db()->__invalidate_all(this);
|
2020-10-03 03:02:52 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2016-12-28 14:06:09 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
|
|
|
void
|
|
|
|
vector<_Tp, _Allocator>::__invalidate_iterators_past(pointer __new_last) {
|
2020-10-03 03:02:52 +08:00
|
|
|
#if _LIBCPP_DEBUG_LEVEL == 2
|
2016-12-28 14:06:09 +08:00
|
|
|
__c_node* __c = __get_db()->__find_c_and_lock(this);
|
|
|
|
for (__i_node** __p = __c->end_; __p != __c->beg_; ) {
|
|
|
|
--__p;
|
|
|
|
const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_);
|
|
|
|
if (__i->base() > __new_last) {
|
|
|
|
(*__p)->__c_ = nullptr;
|
|
|
|
if (--__c->end_ != __p)
|
2020-12-08 10:50:15 +08:00
|
|
|
_VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
|
2016-12-28 14:06:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
__get_db()->unlock();
|
|
|
|
#else
|
|
|
|
((void)__new_last);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
// vector<bool>
|
|
|
|
|
|
|
|
template <class _Allocator> class vector<bool, _Allocator>;
|
|
|
|
|
|
|
|
template <class _Allocator> struct hash<vector<bool, _Allocator> >;
|
|
|
|
|
2011-07-03 04:33:23 +08:00
|
|
|
template <class _Allocator>
|
|
|
|
struct __has_storage_type<vector<bool, _Allocator> >
|
|
|
|
{
|
|
|
|
static const bool value = true;
|
|
|
|
};
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Allocator>
|
2017-01-05 07:56:00 +08:00
|
|
|
class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef vector __self;
|
2010-08-22 08:02:43 +08:00
|
|
|
typedef bool value_type;
|
2010-05-12 03:42:16 +08: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-08 00:50:38 +08:00
|
|
|
typedef size_type __storage_type;
|
2010-05-12 03:42:16 +08:00
|
|
|
typedef __bit_iterator<vector, false> pointer;
|
|
|
|
typedef __bit_iterator<vector, true> const_pointer;
|
|
|
|
typedef pointer iterator;
|
|
|
|
typedef const_pointer const_iterator;
|
2011-07-01 05:18:19 +08:00
|
|
|
typedef _VSTD::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
private:
|
2015-04-07 13:21:38 +08:00
|
|
|
typedef typename __rebind_alloc_helper<__alloc_traits, __storage_type>::type __storage_allocator;
|
2010-05-12 03:42:16 +08:00
|
|
|
typedef allocator_traits<__storage_allocator> __storage_traits;
|
|
|
|
typedef typename __storage_traits::pointer __storage_pointer;
|
|
|
|
typedef typename __storage_traits::const_pointer __const_storage_pointer;
|
|
|
|
|
|
|
|
__storage_pointer __begin_;
|
|
|
|
size_type __size_;
|
|
|
|
__compressed_pair<size_type, __storage_allocator> __cap_alloc_;
|
2011-07-09 23:50:42 +08:00
|
|
|
public:
|
2011-07-03 04:33:23 +08:00
|
|
|
typedef __bit_reference<vector> reference;
|
|
|
|
typedef __bit_const_reference<vector> const_reference;
|
2011-07-09 23:50:42 +08:00
|
|
|
private:
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
size_type& __cap() _NOEXCEPT
|
|
|
|
{return __cap_alloc_.first();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const size_type& __cap() const _NOEXCEPT
|
|
|
|
{return __cap_alloc_.first();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
__storage_allocator& __alloc() _NOEXCEPT
|
|
|
|
{return __cap_alloc_.second();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const __storage_allocator& __alloc() const _NOEXCEPT
|
|
|
|
{return __cap_alloc_.second();}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
static const unsigned __bits_per_word = static_cast<unsigned>(sizeof(__storage_type) * CHAR_BIT);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
static size_type __internal_cap_to_external(size_type __n) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return __n * __bits_per_word;}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
static size_type __external_cap_to_internal(size_type __n) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return (__n - 1) / __bits_per_word + 1;}
|
|
|
|
|
|
|
|
public:
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2015-06-04 10:05:41 +08:00
|
|
|
vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value);
|
2015-06-04 08:10:20 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a)
|
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
|
|
|
|
#else
|
|
|
|
_NOEXCEPT;
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
~vector();
|
|
|
|
explicit vector(size_type __n);
|
2013-09-14 08:47:59 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
explicit vector(size_type __n, const allocator_type& __a);
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
vector(size_type __n, const value_type& __v);
|
|
|
|
vector(size_type __n, const value_type& __v, const allocator_type& __a);
|
|
|
|
template <class _InputIterator>
|
|
|
|
vector(_InputIterator __first, _InputIterator __last,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value>::type* = 0);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _InputIterator>
|
|
|
|
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value>::type* = 0);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector(_ForwardIterator __first, _ForwardIterator __last,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0);
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
vector(const vector& __v);
|
|
|
|
vector(const vector& __v, const allocator_type& __a);
|
|
|
|
vector& operator=(const vector& __v);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
vector(initializer_list<value_type> __il);
|
|
|
|
vector(initializer_list<value_type> __il, const allocator_type& __a);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
vector(vector&& __v)
|
2015-07-14 22:46:32 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
|
|
|
_NOEXCEPT;
|
|
|
|
#else
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
2015-07-14 22:46:32 +08:00
|
|
|
#endif
|
2021-03-02 06:08:24 +08:00
|
|
|
vector(vector&& __v, const __identity_t<allocator_type>& __a);
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
vector& operator=(vector&& __v)
|
2015-08-19 02:57:00 +08:00
|
|
|
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector& operator=(initializer_list<value_type> __il)
|
|
|
|
{assign(__il.begin(), __il.end()); return *this;}
|
2017-04-16 10:40:45 +08:00
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator<_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
assign(_InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
assign(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
|
|
|
|
void assign(size_type __n, const value_type& __x);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void assign(initializer_list<value_type> __il)
|
|
|
|
{assign(__il.begin(), __il.end());}
|
2017-04-16 10:40:45 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return allocator_type(this->__alloc());}
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
size_type max_size() const _NOEXCEPT;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
size_type capacity() const _NOEXCEPT
|
|
|
|
{return __internal_cap_to_external(__cap());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
size_type size() const _NOEXCEPT
|
|
|
|
{return __size_;}
|
2017-11-15 13:51:26 +08:00
|
|
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
bool empty() const _NOEXCEPT
|
|
|
|
{return __size_ == 0;}
|
2010-05-12 03:42:16 +08:00
|
|
|
void reserve(size_type __n);
|
2011-06-04 03:40:40 +08:00
|
|
|
void shrink_to_fit() _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
iterator begin() _NOEXCEPT
|
|
|
|
{return __make_iter(0);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator begin() const _NOEXCEPT
|
|
|
|
{return __make_iter(0);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
iterator end() _NOEXCEPT
|
|
|
|
{return __make_iter(__size_);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator end() const _NOEXCEPT
|
|
|
|
{return __make_iter(__size_);}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
reverse_iterator rbegin() _NOEXCEPT
|
|
|
|
{return reverse_iterator(end());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator rbegin() const _NOEXCEPT
|
|
|
|
{return const_reverse_iterator(end());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
reverse_iterator rend() _NOEXCEPT
|
|
|
|
{return reverse_iterator(begin());}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator rend() const _NOEXCEPT
|
|
|
|
{return const_reverse_iterator(begin());}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator cbegin() const _NOEXCEPT
|
|
|
|
{return __make_iter(0);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator cend() const _NOEXCEPT
|
|
|
|
{return __make_iter(__size_);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator crbegin() const _NOEXCEPT
|
|
|
|
{return rbegin();}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reverse_iterator crend() const _NOEXCEPT
|
|
|
|
{return rend();}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __make_ref(__n);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const {return __make_ref(__n);}
|
|
|
|
reference at(size_type __n);
|
|
|
|
const_reference at(size_type __n) const;
|
|
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY reference front() {return __make_ref(0);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference front() const {return __make_ref(0);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY reference back() {return __make_ref(__size_ - 1);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY const_reference back() const {return __make_ref(__size_ - 1);}
|
|
|
|
|
|
|
|
void push_back(const value_type& __x);
|
2013-08-14 07:54:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
template <class... _Args>
|
2017-01-25 07:09:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
|
|
|
_LIBCPP_INLINE_VISIBILITY reference emplace_back(_Args&&... __args)
|
|
|
|
#else
|
|
|
|
_LIBCPP_INLINE_VISIBILITY void emplace_back(_Args&&... __args)
|
|
|
|
#endif
|
|
|
|
{
|
2016-07-21 11:20:17 +08:00
|
|
|
push_back ( value_type ( _VSTD::forward<_Args>(__args)... ));
|
2017-01-25 07:09:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
2016-07-21 11:20:17 +08:00
|
|
|
return this->back();
|
2017-01-25 07:09:12 +08:00
|
|
|
#endif
|
2016-07-21 11:20:17 +08:00
|
|
|
}
|
2013-08-14 07:54:12 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void pop_back() {--__size_;}
|
|
|
|
|
2013-08-14 07:54:12 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
template <class... _Args>
|
|
|
|
_LIBCPP_INLINE_VISIBILITY iterator emplace(const_iterator position, _Args&&... __args)
|
|
|
|
{ return insert ( position, value_type ( _VSTD::forward<_Args>(__args)... )); }
|
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator insert(const_iterator __position, const value_type& __x);
|
|
|
|
iterator insert(const_iterator __position, size_type __n, const value_type& __x);
|
|
|
|
iterator insert(const_iterator __position, size_type __n, const_reference __x);
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator
|
|
|
|
>::type
|
|
|
|
insert(const_iterator __position, _InputIterator __first, _InputIterator __last);
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator
|
|
|
|
>::type
|
|
|
|
insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last);
|
2017-04-16 10:40:45 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator insert(const_iterator __position, initializer_list<value_type> __il)
|
|
|
|
{return insert(__position, __il.begin(), __il.end());}
|
2017-04-16 10:40:45 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position);
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator erase(const_iterator __first, const_iterator __last);
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
void clear() _NOEXCEPT {__size_ = 0;}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
void swap(vector&)
|
2015-07-14 04:04:56 +08:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
|
|
_NOEXCEPT;
|
|
|
|
#else
|
2016-12-28 14:06:09 +08:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
2015-07-14 04:04:56 +08:00
|
|
|
__is_nothrow_swappable<allocator_type>::value);
|
|
|
|
#endif
|
2016-04-07 22:20:31 +08:00
|
|
|
static void swap(reference __x, reference __y) _NOEXCEPT { _VSTD::swap(__x, __y); }
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
void resize(size_type __sz, value_type __x = false);
|
2011-06-04 03:40:40 +08:00
|
|
|
void flip() _NOEXCEPT;
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
bool __invariants() const;
|
|
|
|
|
|
|
|
private:
|
2022-02-04 06:09:37 +08:00
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
|
|
|
|
void __throw_length_error() const {
|
|
|
|
_VSTD::__throw_length_error("vector");
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
|
|
|
|
void __throw_out_of_range() const {
|
|
|
|
_VSTD::__throw_out_of_range("vector");
|
|
|
|
}
|
|
|
|
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
|
2018-05-23 00:20:28 +08:00
|
|
|
void __vallocate(size_type __n);
|
|
|
|
void __vdeallocate() _NOEXCEPT;
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2013-08-15 02:00:20 +08:00
|
|
|
static size_type __align_it(size_type __new_size) _NOEXCEPT
|
2018-10-01 09:59:37 +08:00
|
|
|
{return __new_size + (__bits_per_word-1) & ~((size_type)__bits_per_word-1);}
|
2010-12-17 22:46:43 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, bool __x);
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
__construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
void __append(size_type __n, const_reference __x);
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
reference __make_ref(size_type __pos) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_reference __make_ref(size_type __pos) const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return const_reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
iterator __make_iter(size_type __pos) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return iterator(__begin_ + __pos / __bits_per_word, static_cast<unsigned>(__pos % __bits_per_word));}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
const_iterator __make_iter(size_type __pos) const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return const_iterator(__begin_ + __pos / __bits_per_word, static_cast<unsigned>(__pos % __bits_per_word));}
|
2011-06-04 03:40:40 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
|
|
iterator __const_iterator_cast(const_iterator __p) _NOEXCEPT
|
2013-06-28 03:35:32 +08:00
|
|
|
{return begin() + (__p - cbegin());}
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void __copy_assign_alloc(const vector& __v)
|
|
|
|
{__copy_assign_alloc(__v, integral_constant<bool,
|
|
|
|
__storage_traits::propagate_on_container_copy_assignment::value>());}
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void __copy_assign_alloc(const vector& __c, true_type)
|
|
|
|
{
|
|
|
|
if (__alloc() != __c.__alloc())
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
2010-05-12 03:42:16 +08:00
|
|
|
__alloc() = __c.__alloc();
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-12-02 04:21:04 +08:00
|
|
|
void __copy_assign_alloc(const vector&, false_type)
|
2010-05-12 03:42:16 +08:00
|
|
|
{}
|
|
|
|
|
|
|
|
void __move_assign(vector& __c, false_type);
|
2011-06-04 03:40:40 +08:00
|
|
|
void __move_assign(vector& __c, true_type)
|
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void __move_assign_alloc(vector& __c)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(
|
|
|
|
!__storage_traits::propagate_on_container_move_assignment::value ||
|
|
|
|
is_nothrow_move_assignable<allocator_type>::value)
|
2010-05-12 03:42:16 +08:00
|
|
|
{__move_assign_alloc(__c, integral_constant<bool,
|
|
|
|
__storage_traits::propagate_on_container_move_assignment::value>());}
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-09-03 04:42:31 +08:00
|
|
|
void __move_assign_alloc(vector& __c, true_type)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-07-01 05:18:19 +08:00
|
|
|
__alloc() = _VSTD::move(__c.__alloc());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-12-02 04:21:04 +08:00
|
|
|
void __move_assign_alloc(vector&, false_type)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{}
|
|
|
|
|
2011-06-04 03:40:40 +08:00
|
|
|
size_t __hash_code() const _NOEXCEPT;
|
2010-05-12 03:42:16 +08: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-18 01:10:18 +08:00
|
|
|
friend struct __bit_array<vector>;
|
2017-01-05 07:56:00 +08:00
|
|
|
friend struct _LIBCPP_TEMPLATE_VIS hash<vector>;
|
2010-05-12 03:42:16 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<bool, _Allocator>::__invalidate_all_iterators()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
template <class _Allocator>
|
|
|
|
void
|
2018-05-23 00:20:28 +08:00
|
|
|
vector<bool, _Allocator>::__vallocate(size_type __n)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
|
|
|
__n = __external_cap_to_internal(__n);
|
|
|
|
this->__begin_ = __storage_traits::allocate(this->__alloc(), __n);
|
|
|
|
this->__size_ = 0;
|
|
|
|
this->__cap() = __n;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
void
|
2018-05-23 00:20:28 +08:00
|
|
|
vector<bool, _Allocator>::__vdeallocate() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (this->__begin_ != nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__storage_traits::deallocate(this->__alloc(), this->__begin_, __cap());
|
|
|
|
__invalidate_all_iterators();
|
2013-06-28 03:35:32 +08:00
|
|
|
this->__begin_ = nullptr;
|
2010-05-12 03:42:16 +08:00
|
|
|
this->__size_ = this->__cap() = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
typename vector<bool, _Allocator>::size_type
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<bool, _Allocator>::max_size() const _NOEXCEPT
|
2010-05-12 03:42:16 +08: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>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<bool, _Allocator>::size_type
|
|
|
|
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;
|
2021-07-27 06:23:00 +08:00
|
|
|
return _VSTD::max(2 * __cap, __align_it(__new_size));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default constructs __n objects starting at __end_
|
|
|
|
// Precondition: __n > 0
|
|
|
|
// Precondition: size() + __n <= capacity()
|
|
|
|
// Postcondition: size() == size() + __n
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
vector<bool, _Allocator>::__construct_at_end(size_type __n, bool __x)
|
|
|
|
{
|
|
|
|
size_type __old_size = this->__size_;
|
|
|
|
this->__size_ += __n;
|
2018-10-24 04:07:45 +08: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);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(__make_iter(__old_size), __n, __x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
vector<bool, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last)
|
|
|
|
{
|
|
|
|
size_type __old_size = this->__size_;
|
2011-07-01 05:18:19 +08:00
|
|
|
this->__size_ += _VSTD::distance(__first, __last);
|
2018-10-24 04:07:45 +08: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);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__first, __last, __make_iter(__old_size));
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<bool, _Allocator>::vector()
|
2015-06-04 10:05:41 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<bool, _Allocator>::vector(const allocator_type& __a)
|
2015-06-04 08:10:20 +08:00
|
|
|
#if _LIBCPP_STD_VER <= 14
|
|
|
|
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
|
|
|
|
#else
|
|
|
|
_NOEXCEPT
|
|
|
|
#endif
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(size_type __n)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-14 08:47:59 +08:00
|
|
|
#if _LIBCPP_STD_VER > 11
|
|
|
|
template <class _Allocator>
|
|
|
|
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-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2013-09-14 08:47:59 +08:00
|
|
|
__construct_at_end(__n, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(size_type __n, const value_type& __x)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
|
|
|
|
{
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__n, __x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value>::type*)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
push_back(*__first);
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (__begin_ != nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
__storage_traits::deallocate(__alloc(), __begin_, __cap());
|
|
|
|
__invalidate_all_iterators();
|
|
|
|
throw;
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value>::type*)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
|
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
push_back(*__first);
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (__begin_ != nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
__storage_traits::deallocate(__alloc(), __begin_, __cap());
|
|
|
|
__invalidate_all_iterators();
|
|
|
|
throw;
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-07-01 05:18:19 +08:00
|
|
|
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__first, __last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
|
2019-11-18 14:46:58 +08:00
|
|
|
typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
|
|
|
|
{
|
2011-07-01 05:18:19 +08:00
|
|
|
size_type __n = static_cast<size_type>(_VSTD::distance(__first, __last));
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__first, __last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2011-08-13 05:56:02 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(initializer_list<value_type> __il)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
2019-12-17 07:23:39 +08:00
|
|
|
__cap_alloc_(0, __default_init_tag())
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
size_type __n = static_cast<size_type>(__il.size());
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__il.begin(), __il.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, static_cast<__storage_allocator>(__a))
|
|
|
|
{
|
|
|
|
size_type __n = static_cast<size_type>(__il.size());
|
|
|
|
if (__n > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__il.begin(), __il.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2011-08-13 05:56:02 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::~vector()
|
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (__begin_ != nullptr)
|
2010-05-12 03:42:16 +08:00
|
|
|
__storage_traits::deallocate(__alloc(), __begin_, __cap());
|
|
|
|
__invalidate_all_iterators();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(const vector& __v)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, __storage_traits::select_on_container_copy_construction(__v.__alloc()))
|
|
|
|
{
|
|
|
|
if (__v.size() > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__v.size());
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__v.begin(), __v.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>::vector(const vector& __v, const allocator_type& __a)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, __a)
|
|
|
|
{
|
|
|
|
if (__v.size() > 0)
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vallocate(__v.size());
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__v.begin(), __v.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
vector<bool, _Allocator>&
|
|
|
|
vector<bool, _Allocator>::operator=(const vector& __v)
|
|
|
|
{
|
2021-09-29 01:15:18 +08:00
|
|
|
if (this != _VSTD::addressof(__v))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__copy_assign_alloc(__v);
|
|
|
|
if (__v.__size_)
|
|
|
|
{
|
|
|
|
if (__v.__size_ > capacity())
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__v.__size_);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__v.__begin_, __v.__begin_ + __external_cap_to_internal(__v.__size_), __begin_);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
__size_ = __v.__size_;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-04-16 10:40:45 +08:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-09-05 07:28:19 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
template <class _Allocator>
|
2018-06-06 06:32:52 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY vector<bool, _Allocator>::vector(vector&& __v)
|
2015-07-14 22:46:32 +08:00
|
|
|
#if _LIBCPP_STD_VER > 14
|
2018-06-06 06:32:52 +08:00
|
|
|
_NOEXCEPT
|
2015-07-14 22:46:32 +08:00
|
|
|
#else
|
2018-06-06 06:32:52 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
2015-07-14 22:46:32 +08:00
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
: __begin_(__v.__begin_),
|
|
|
|
__size_(__v.__size_),
|
[libc++] Consistently replace `std::` qualification with `_VSTD::` or nothing. NFCI.
I used a lot of `git grep` to find places where `std::` was being used
outside of comments and assert-messages. There were three outcomes:
- Qualified function calls, e.g. `std::move` becomes `_VSTD::move`.
This is the most common case.
- Typenames that don't need qualification, e.g. `std::allocator` becomes `allocator`.
Leaving these as `_VSTD::allocator` would also be fine, but I decided
that removing the qualification is more consistent with existing practice.
- Names that specifically need un-versioned `std::` qualification,
or that I wasn't sure about. For example, I didn't touch any code in
<atomic>, <math.h>, <new>, or any ext/ or experimental/ headers;
and I didn't touch any instances of `std::type_info`.
In some deduction guides, we were accidentally using `class Alloc = typename std::allocator<T>`,
despite `std::allocator<T>`'s type-ness not being template-dependent.
Because `std::allocator` is a qualified name, this did parse as we intended;
but what we meant was simply `class Alloc = allocator<T>`.
Differential Revision: https://reviews.llvm.org/D92250
2020-11-28 00:02:06 +08:00
|
|
|
__cap_alloc_(_VSTD::move(__v.__cap_alloc_)) {
|
2013-06-28 03:35:32 +08:00
|
|
|
__v.__begin_ = nullptr;
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.__size_ = 0;
|
|
|
|
__v.__cap() = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2021-03-02 06:08:24 +08:00
|
|
|
vector<bool, _Allocator>::vector(vector&& __v, const __identity_t<allocator_type>& __a)
|
2013-06-28 03:35:32 +08:00
|
|
|
: __begin_(nullptr),
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_(0),
|
|
|
|
__cap_alloc_(0, __a)
|
|
|
|
{
|
|
|
|
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-23 00:20:28 +08:00
|
|
|
__vallocate(__v.size());
|
2010-05-12 03:42:16 +08:00
|
|
|
__construct_at_end(__v.begin(), __v.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
vector<bool, _Allocator>&
|
|
|
|
vector<bool, _Allocator>::operator=(vector&& __v)
|
2015-08-19 02:57:00 +08:00
|
|
|
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__move_assign(__v, integral_constant<bool,
|
|
|
|
__storage_traits::propagate_on_container_move_assignment::value>());
|
2012-10-13 10:03:45 +08:00
|
|
|
return *this;
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
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>
|
|
|
|
void
|
|
|
|
vector<bool, _Allocator>::__move_assign(vector& __c, true_type)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
2014-07-21 23:15:15 +08:00
|
|
|
__move_assign_alloc(__c);
|
2010-05-12 03:42:16 +08:00
|
|
|
this->__begin_ = __c.__begin_;
|
|
|
|
this->__size_ = __c.__size_;
|
|
|
|
this->__cap() = __c.__cap();
|
|
|
|
__c.__begin_ = nullptr;
|
|
|
|
__c.__cap() = __c.__size_ = 0;
|
|
|
|
}
|
2010-09-05 07:28:19 +08:00
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // !_LIBCPP_CXX03_LANG
|
2010-05-12 03:42:16 +08:00
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
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 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.reserve(__recommend(__n));
|
|
|
|
__v.__size_ = __n;
|
|
|
|
swap(__v);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(begin(), __n, __x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2016-12-28 14:06:09 +08:00
|
|
|
__invalidate_all_iterators();
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator<_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
vector<bool, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
for (; __first != __last; ++__first)
|
|
|
|
push_back(*__first);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
>::type
|
|
|
|
vector<bool, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
|
|
|
|
{
|
|
|
|
clear();
|
2016-12-24 07:37:52 +08:00
|
|
|
difference_type __ns = _VSTD::distance(__first, __last);
|
|
|
|
_LIBCPP_ASSERT(__ns >= 0, "invalid range specified");
|
|
|
|
const size_t __n = static_cast<size_type>(__ns);
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__n)
|
|
|
|
{
|
|
|
|
if (__n > capacity())
|
|
|
|
{
|
2018-05-23 00:20:28 +08:00
|
|
|
__vdeallocate();
|
|
|
|
__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
__construct_at_end(__first, __last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
void
|
|
|
|
vector<bool, _Allocator>::reserve(size_type __n)
|
|
|
|
{
|
|
|
|
if (__n > capacity())
|
|
|
|
{
|
2021-10-21 17:40:05 +08:00
|
|
|
if (__n > max_size())
|
|
|
|
this->__throw_length_error();
|
2021-10-21 17:38:56 +08:00
|
|
|
vector __v(this->get_allocator());
|
2018-05-23 00:20:28 +08:00
|
|
|
__v.__vallocate(__n);
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.__construct_at_end(this->begin(), this->end());
|
|
|
|
swap(__v);
|
|
|
|
__invalidate_all_iterators();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
void
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<bool, _Allocator>::shrink_to_fit() _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
if (__external_cap_to_internal(size()) > __cap())
|
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
vector(*this, allocator_type(__alloc())).swap(*this);
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08: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>
|
|
|
|
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>
|
|
|
|
typename vector<bool, _Allocator>::iterator
|
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, const value_type& __x)
|
|
|
|
{
|
|
|
|
iterator __r;
|
|
|
|
if (size() < capacity())
|
|
|
|
{
|
|
|
|
const_iterator __old_end = end();
|
|
|
|
++__size_;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy_backward(__position, __old_end, end());
|
2010-05-12 03:42:16 +08:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-21 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.reserve(__recommend(__size_ + 1));
|
|
|
|
__v.__size_ = __size_ + 1;
|
2011-07-01 05:18:19 +08:00
|
|
|
__r = _VSTD::copy(cbegin(), __position, __v.begin());
|
|
|
|
_VSTD::copy_backward(__position, cend(), __v.end());
|
2010-05-12 03:42:16 +08:00
|
|
|
swap(__v);
|
|
|
|
}
|
|
|
|
*__r = __x;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
typename vector<bool, _Allocator>::iterator
|
|
|
|
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;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy_backward(__position, __old_end, end());
|
2010-05-12 03:42:16 +08:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-21 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2011-07-01 05:18:19 +08:00
|
|
|
__r = _VSTD::copy(cbegin(), __position, __v.begin());
|
|
|
|
_VSTD::copy_backward(__position, cend(), __v.end());
|
2010-05-12 03:42:16 +08:00
|
|
|
swap(__v);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(__r, __n, __x);
|
2010-05-12 03:42:16 +08:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _InputIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_input_iterator <_InputIterator>::value &&
|
|
|
|
!__is_cpp17_forward_iterator<_InputIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<bool, _Allocator>::iterator
|
|
|
|
>::type
|
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last)
|
|
|
|
{
|
|
|
|
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 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
if (__first != __last)
|
|
|
|
{
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
try
|
|
|
|
{
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.assign(__first, __last);
|
|
|
|
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;
|
|
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
erase(__old_end, end());
|
|
|
|
throw;
|
|
|
|
}
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
__p = _VSTD::rotate(__p, __old_end, end());
|
2010-05-12 03:42:16 +08:00
|
|
|
insert(__p, __v.begin(), __v.end());
|
|
|
|
return begin() + __off;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
template <class _ForwardIterator>
|
|
|
|
typename enable_if
|
|
|
|
<
|
2019-11-18 14:46:58 +08:00
|
|
|
__is_cpp17_forward_iterator<_ForwardIterator>::value,
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<bool, _Allocator>::iterator
|
|
|
|
>::type
|
|
|
|
vector<bool, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last)
|
|
|
|
{
|
2016-12-11 13:31:00 +08:00
|
|
|
const difference_type __n_signed = _VSTD::distance(__first, __last);
|
|
|
|
_LIBCPP_ASSERT(__n_signed >= 0, "invalid range specified");
|
|
|
|
const size_type __n = static_cast<size_type>(__n_signed);
|
2010-05-12 03:42:16 +08:00
|
|
|
iterator __r;
|
|
|
|
size_type __c = capacity();
|
|
|
|
if (__n <= __c && size() <= __c - __n)
|
|
|
|
{
|
|
|
|
const_iterator __old_end = end();
|
|
|
|
__size_ += __n;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy_backward(__position, __old_end, end());
|
2010-05-12 03:42:16 +08:00
|
|
|
__r = __const_iterator_cast(__position);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-21 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2011-07-01 05:18:19 +08:00
|
|
|
__r = _VSTD::copy(cbegin(), __position, __v.begin());
|
|
|
|
_VSTD::copy_backward(__position, cend(), __v.end());
|
2010-05-12 03:42:16 +08:00
|
|
|
swap(__v);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__first, __last, __r);
|
2010-05-12 03:42:16 +08:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
typename vector<bool, _Allocator>::iterator
|
|
|
|
vector<bool, _Allocator>::erase(const_iterator __position)
|
|
|
|
{
|
|
|
|
iterator __r = __const_iterator_cast(__position);
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__position + 1, this->cend(), __r);
|
2010-05-12 03:42:16 +08:00
|
|
|
--__size_;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
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;
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::copy(__last, this->cend(), __r);
|
2010-05-12 03:42:16 +08:00
|
|
|
__size_ -= __d;
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Allocator>
|
|
|
|
void
|
|
|
|
vector<bool, _Allocator>::swap(vector& __x)
|
2015-07-14 04:04:56 +08:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
|
|
|
_NOEXCEPT
|
|
|
|
#else
|
2016-12-28 14:06:09 +08:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
2015-07-14 04:04:56 +08:00
|
|
|
__is_nothrow_swappable<allocator_type>::value)
|
|
|
|
#endif
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::swap(this->__begin_, __x.__begin_);
|
|
|
|
_VSTD::swap(this->__size_, __x.__size_);
|
|
|
|
_VSTD::swap(this->__cap(), __x.__cap());
|
2020-11-19 07:54:38 +08:00
|
|
|
_VSTD::__swap_allocator(this->__alloc(), __x.__alloc(),
|
2015-07-14 04:04:56 +08:00
|
|
|
integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
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 17:38:56 +08:00
|
|
|
vector __v(get_allocator());
|
2010-05-12 03:42:16 +08:00
|
|
|
__v.reserve(__recommend(__size_ + __n));
|
|
|
|
__v.__size_ = __size_ + __n;
|
2011-07-01 05:18:19 +08:00
|
|
|
__r = _VSTD::copy(cbegin(), cend(), __v.begin());
|
2010-05-12 03:42:16 +08:00
|
|
|
swap(__v);
|
|
|
|
}
|
2011-07-01 05:18:19 +08:00
|
|
|
_VSTD::fill_n(__r, __n, __x);
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
__size_ = __sz;
|
|
|
|
}
|
|
|
|
|
2010-08-22 08:02:43 +08:00
|
|
|
template <class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<bool, _Allocator>::flip() _NOEXCEPT
|
2010-05-12 03:42:16 +08: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 08:02:43 +08:00
|
|
|
template <class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
vector<bool, _Allocator>::__invariants() const
|
|
|
|
{
|
2013-06-28 03:35:32 +08:00
|
|
|
if (this->__begin_ == nullptr)
|
2010-05-12 03:42:16 +08: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 08:02:43 +08:00
|
|
|
template <class _Allocator>
|
2010-05-12 03:42:16 +08:00
|
|
|
size_t
|
2011-06-04 03:40:40 +08:00
|
|
|
vector<bool, _Allocator>::__hash_code() const _NOEXCEPT
|
2010-05-12 03:42:16 +08: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-05 07:56:00 +08:00
|
|
|
struct _LIBCPP_TEMPLATE_VIS hash<vector<bool, _Allocator> >
|
2010-05-12 03:42:16 +08:00
|
|
|
: public unary_function<vector<bool, _Allocator>, size_t>
|
|
|
|
{
|
2010-09-24 02:58:28 +08:00
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
2011-06-04 03:40:40 +08:00
|
|
|
size_t operator()(const vector<bool, _Allocator>& __vec) const _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{return __vec.__hash_code();}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
|
|
|
const typename vector<_Tp, _Allocator>::size_type __sz = __x.size();
|
2011-07-01 05:18:19 +08:00
|
|
|
return __sz == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
2011-07-01 05:18:19 +08:00
|
|
|
return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
|
|
|
return __y < __x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
|
|
|
return !(__x < __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
bool
|
|
|
|
operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
|
|
|
|
{
|
|
|
|
return !(__y < __x);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Allocator>
|
2013-10-05 06:09:00 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY
|
2010-05-12 03:42:16 +08:00
|
|
|
void
|
|
|
|
swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y)
|
2011-06-04 03:40:40 +08:00
|
|
|
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
__x.swap(__y);
|
|
|
|
}
|
|
|
|
|
2018-12-15 02:49:35 +08:00
|
|
|
#if _LIBCPP_STD_VER > 17
|
|
|
|
template <class _Tp, class _Allocator, class _Up>
|
2020-05-02 19:58:03 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type
|
|
|
|
erase(vector<_Tp, _Allocator>& __c, const _Up& __v) {
|
|
|
|
auto __old_size = __c.size();
|
|
|
|
__c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end());
|
|
|
|
return __old_size - __c.size();
|
|
|
|
}
|
2018-12-15 02:49:35 +08:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator, class _Predicate>
|
2020-05-02 19:58:03 +08:00
|
|
|
inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type
|
|
|
|
erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) {
|
|
|
|
auto __old_size = __c.size();
|
|
|
|
__c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end());
|
|
|
|
return __old_size - __c.size();
|
|
|
|
}
|
2018-12-15 02:49:35 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
2017-06-01 06:07:49 +08:00
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
|
2021-04-21 00:03:32 +08:00
|
|
|
#endif // _LIBCPP_VECTOR
|