2010-05-11 19:42:16 +00:00
|
|
|
// -*- C++ -*-
|
2021-11-17 21:25:01 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
2019-01-19 10:56:40 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_LIST
|
|
|
|
#define _LIBCPP_LIST
|
|
|
|
|
|
|
|
/*
|
|
|
|
list synopsis
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
|
|
|
|
template <class T, class Alloc = allocator<T> >
|
|
|
|
class list
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
// types:
|
|
|
|
typedef T value_type;
|
|
|
|
typedef Alloc allocator_type;
|
|
|
|
typedef typename allocator_type::reference reference;
|
|
|
|
typedef typename allocator_type::const_reference const_reference;
|
|
|
|
typedef typename allocator_type::pointer pointer;
|
|
|
|
typedef typename allocator_type::const_pointer const_pointer;
|
|
|
|
typedef implementation-defined iterator;
|
|
|
|
typedef implementation-defined const_iterator;
|
|
|
|
typedef implementation-defined size_type;
|
|
|
|
typedef implementation-defined difference_type;
|
|
|
|
typedef reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef reverse_iterator<const_iterator> const_reverse_iterator;
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
list()
|
|
|
|
noexcept(is_nothrow_default_constructible<allocator_type>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
explicit list(const allocator_type& a);
|
|
|
|
explicit list(size_type n);
|
2013-09-09 18:19:45 +00:00
|
|
|
explicit list(size_type n, const allocator_type& a); // C++14
|
2010-05-11 19:42:16 +00:00
|
|
|
list(size_type n, const value_type& value);
|
|
|
|
list(size_type n, const value_type& value, const allocator_type& a);
|
|
|
|
template <class Iter>
|
|
|
|
list(Iter first, Iter last);
|
|
|
|
template <class Iter>
|
|
|
|
list(Iter first, Iter last, const allocator_type& a);
|
2023-07-11 00:16:56 +00:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
list(const list& x);
|
|
|
|
list(const list&, const allocator_type& a);
|
2011-06-03 17:30:28 +00:00
|
|
|
list(list&& x)
|
|
|
|
noexcept(is_nothrow_move_constructible<allocator_type>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
list(list&&, const allocator_type& a);
|
|
|
|
list(initializer_list<value_type>);
|
|
|
|
list(initializer_list<value_type>, const allocator_type& a);
|
|
|
|
|
|
|
|
~list();
|
|
|
|
|
|
|
|
list& operator=(const list& x);
|
2011-06-03 17:30:28 +00:00
|
|
|
list& operator=(list&& x)
|
|
|
|
noexcept(
|
|
|
|
allocator_type::propagate_on_container_move_assignment::value &&
|
|
|
|
is_nothrow_move_assignable<allocator_type>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
list& operator=(initializer_list<value_type>);
|
|
|
|
template <class Iter>
|
|
|
|
void assign(Iter first, Iter last);
|
2023-07-11 00:16:56 +00:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
void assign_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void assign(size_type n, const value_type& t);
|
|
|
|
void assign(initializer_list<value_type>);
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
allocator_type get_allocator() const noexcept;
|
|
|
|
|
|
|
|
iterator begin() noexcept;
|
|
|
|
const_iterator begin() const noexcept;
|
|
|
|
iterator end() noexcept;
|
|
|
|
const_iterator end() const noexcept;
|
|
|
|
reverse_iterator rbegin() noexcept;
|
|
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
|
|
reverse_iterator rend() noexcept;
|
|
|
|
const_reverse_iterator rend() const noexcept;
|
|
|
|
const_iterator cbegin() const noexcept;
|
|
|
|
const_iterator cend() const noexcept;
|
|
|
|
const_reverse_iterator crbegin() const noexcept;
|
|
|
|
const_reverse_iterator crend() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
reference front();
|
|
|
|
const_reference front() const;
|
|
|
|
reference back();
|
|
|
|
const_reference back() const;
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
bool empty() const noexcept;
|
|
|
|
size_type size() const noexcept;
|
|
|
|
size_type max_size() const noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class... Args>
|
2017-01-24 23:09:12 +00:00
|
|
|
reference emplace_front(Args&&... args); // reference in C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
void pop_front();
|
|
|
|
template <class... Args>
|
2017-01-24 23:09:12 +00:00
|
|
|
reference emplace_back(Args&&... args); // reference in C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
void pop_back();
|
|
|
|
void push_front(const value_type& x);
|
|
|
|
void push_front(value_type&& x);
|
2023-07-11 00:16:56 +00:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
void prepend_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
void push_back(const value_type& x);
|
|
|
|
void push_back(value_type&& x);
|
2023-07-11 00:16:56 +00:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
void append_range(R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
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 Iter>
|
|
|
|
iterator insert(const_iterator position, Iter first, Iter last);
|
2023-07-11 00:16:56 +00:00
|
|
|
template<container-compatible-range<T> R>
|
|
|
|
iterator insert_range(const_iterator position, R&& rg); // C++23
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator insert(const_iterator position, initializer_list<value_type> il);
|
|
|
|
|
|
|
|
iterator erase(const_iterator position);
|
|
|
|
iterator erase(const_iterator position, const_iterator last);
|
|
|
|
|
|
|
|
void resize(size_type sz);
|
|
|
|
void resize(size_type sz, const value_type& c);
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
void swap(list&)
|
2015-07-13 20:04:56 +00:00
|
|
|
noexcept(allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
2011-06-03 17:30:28 +00:00
|
|
|
void clear() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
void splice(const_iterator position, list& x);
|
|
|
|
void splice(const_iterator position, list&& x);
|
|
|
|
void splice(const_iterator position, list& x, const_iterator i);
|
|
|
|
void splice(const_iterator position, list&& x, const_iterator i);
|
|
|
|
void splice(const_iterator position, list& x, const_iterator first,
|
|
|
|
const_iterator last);
|
|
|
|
void splice(const_iterator position, list&& x, const_iterator first,
|
|
|
|
const_iterator last);
|
|
|
|
|
2019-07-08 03:45:28 +00:00
|
|
|
size_type remove(const value_type& value); // void before C++20
|
|
|
|
template <class Pred>
|
|
|
|
size_type remove_if(Pred pred); // void before C++20
|
|
|
|
size_type unique(); // void before C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class BinaryPredicate>
|
2019-07-08 03:45:28 +00:00
|
|
|
size_type unique(BinaryPredicate binary_pred); // void before C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
void merge(list& x);
|
|
|
|
void merge(list&& x);
|
|
|
|
template <class Compare>
|
|
|
|
void merge(list& x, Compare comp);
|
|
|
|
template <class Compare>
|
|
|
|
void merge(list&& x, Compare comp);
|
|
|
|
void sort();
|
|
|
|
template <class Compare>
|
|
|
|
void sort(Compare comp);
|
2011-06-03 17:30:28 +00:00
|
|
|
void reverse() noexcept;
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2018-05-20 14:05:31 +00:00
|
|
|
|
|
|
|
template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
|
|
|
|
list(InputIterator, InputIterator, Allocator = Allocator())
|
|
|
|
-> list<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17
|
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>>
|
|
|
|
list(from_range_t, R&&, Allocator = Allocator())
|
|
|
|
-> list<ranges::range_value_t<R>, Allocator>; // C++23
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, class Alloc>
|
|
|
|
bool operator==(const list<T,Alloc>& x, const list<T,Alloc>& y);
|
|
|
|
template <class T, class Alloc>
|
2022-08-20 20:27:32 +00:00
|
|
|
bool operator< (const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, class Alloc>
|
2022-08-20 20:27:32 +00:00
|
|
|
bool operator!=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, class Alloc>
|
2022-08-20 20:27:32 +00:00
|
|
|
bool operator> (const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, class Alloc>
|
2022-08-20 20:27:32 +00:00
|
|
|
bool operator>=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, class Alloc>
|
2022-08-20 20:27:32 +00:00
|
|
|
bool operator<=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20
|
|
|
|
template<class T, class Allocator>
|
|
|
|
synth-three-way-result<T> operator<=>(const list<T, Allocator>& x,
|
|
|
|
const list<T, Allocator>& y); // since C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class T, class Alloc>
|
2011-06-03 17:30:28 +00:00
|
|
|
void swap(list<T,Alloc>& x, list<T,Alloc>& y)
|
|
|
|
noexcept(noexcept(x.swap(y)));
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class T, class Allocator, class U>
|
2020-05-02 11:58:03 +00:00
|
|
|
typename list<T, Allocator>::size_type
|
2022-08-20 20:27:32 +00:00
|
|
|
erase(list<T, Allocator>& c, const U& value); // since C++20
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class T, class Allocator, class Predicate>
|
2020-05-02 11:58:03 +00:00
|
|
|
typename list<T, Allocator>::size_type
|
2022-08-20 20:27:32 +00:00
|
|
|
erase_if(list<T, Allocator>& c, Predicate pred); // since C++20
|
2018-12-14 18:49:35 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
} // std
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2022-02-15 17:18:08 +00:00
|
|
|
#include <__algorithm/comp.h>
|
|
|
|
#include <__algorithm/equal.h>
|
|
|
|
#include <__algorithm/lexicographical_compare.h>
|
2022-08-20 20:27:32 +00:00
|
|
|
#include <__algorithm/lexicographical_compare_three_way.h>
|
2022-02-15 17:18:08 +00:00
|
|
|
#include <__algorithm/min.h>
|
2022-03-25 16:55:36 +00:00
|
|
|
#include <__assert> // all public C++ headers provide the assertion handler
|
2023-03-29 20:48:20 +00:00
|
|
|
#include <__availability>
|
2010-05-11 19:42:16 +00:00
|
|
|
#include <__config>
|
2021-09-26 13:47:42 +00:00
|
|
|
#include <__format/enable_insertable.h>
|
2022-06-10 17:53:10 +00:00
|
|
|
#include <__iterator/distance.h>
|
|
|
|
#include <__iterator/iterator_traits.h>
|
|
|
|
#include <__iterator/move_iterator.h>
|
|
|
|
#include <__iterator/next.h>
|
|
|
|
#include <__iterator/prev.h>
|
|
|
|
#include <__iterator/reverse_iterator.h>
|
2022-09-04 22:01:15 +00:00
|
|
|
#include <__memory/addressof.h>
|
2023-09-15 14:10:26 +00:00
|
|
|
#include <__memory/allocation_guard.h>
|
2022-09-04 22:01:15 +00:00
|
|
|
#include <__memory/allocator.h>
|
|
|
|
#include <__memory/allocator_traits.h>
|
|
|
|
#include <__memory/compressed_pair.h>
|
2023-10-13 03:13:08 +00:00
|
|
|
#include <__memory/construct_at.h>
|
2022-09-04 22:01:15 +00:00
|
|
|
#include <__memory/pointer_traits.h>
|
[libc++] Use uninitialized algorithms for vector
Reviewed By: ldionne, #libc
Spies: huixie90, eaeltsin, joanahalili, bgraur, alexfh, hans, avogelsgesang, augusto2112, libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D128146
2022-07-26 14:13:56 +00:00
|
|
|
#include <__memory/swap_allocator.h>
|
2022-10-06 20:53:30 +00:00
|
|
|
#include <__memory_resource/polymorphic_allocator.h>
|
2023-07-11 00:16:56 +00:00
|
|
|
#include <__ranges/access.h>
|
|
|
|
#include <__ranges/concepts.h>
|
|
|
|
#include <__ranges/container_compatible_range.h>
|
|
|
|
#include <__ranges/from_range.h>
|
2023-02-12 11:32:36 +00:00
|
|
|
#include <__type_traits/conditional.h>
|
2022-09-04 22:01:15 +00:00
|
|
|
#include <__type_traits/is_allocator.h>
|
2023-02-12 11:32:36 +00:00
|
|
|
#include <__type_traits/is_nothrow_default_constructible.h>
|
|
|
|
#include <__type_traits/is_nothrow_move_assignable.h>
|
|
|
|
#include <__type_traits/is_nothrow_move_constructible.h>
|
|
|
|
#include <__type_traits/is_pointer.h>
|
|
|
|
#include <__type_traits/is_same.h>
|
|
|
|
#include <__type_traits/type_identity.h>
|
2021-06-05 02:47:47 +00:00
|
|
|
#include <__utility/forward.h>
|
2022-03-05 18:17:07 +00:00
|
|
|
#include <__utility/move.h>
|
|
|
|
#include <__utility/swap.h>
|
2022-09-04 22:01:15 +00:00
|
|
|
#include <cstring>
|
2021-05-19 15:57:04 +00:00
|
|
|
#include <limits>
|
2023-10-13 03:13:08 +00:00
|
|
|
#include <new> // __launder
|
2018-09-12 19:41:40 +00:00
|
|
|
#include <version>
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-06-16 20:43:46 +00:00
|
|
|
// standard-mandated includes
|
|
|
|
|
|
|
|
// [iterator.range]
|
|
|
|
#include <__iterator/access.h>
|
|
|
|
#include <__iterator/data.h>
|
|
|
|
#include <__iterator/empty.h>
|
|
|
|
#include <__iterator/reverse_access.h>
|
|
|
|
#include <__iterator/size.h>
|
|
|
|
|
|
|
|
// [list.syn]
|
|
|
|
#include <compare>
|
|
|
|
#include <initializer_list>
|
|
|
|
|
2011-10-17 20:05:10 +00:00
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
2022-02-02 01:16:40 +00:00
|
|
|
# pragma GCC system_header
|
2011-10-17 20:05:10 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2017-05-31 22:07:49 +00:00
|
|
|
_LIBCPP_PUSH_MACROS
|
|
|
|
#include <__undef_macros>
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
2011-06-14 19:58:17 +00:00
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
struct __list_node;
|
2015-12-30 20:57:59 +00:00
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
struct __list_node_base;
|
|
|
|
|
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
struct __list_node_pointer_traits {
|
2022-09-05 22:33:34 +00:00
|
|
|
typedef __rebind_pointer_t<_VoidPtr, __list_node<_Tp, _VoidPtr> > __node_pointer;
|
|
|
|
typedef __rebind_pointer_t<_VoidPtr, __list_node_base<_Tp, _VoidPtr> > __base_pointer;
|
2015-12-30 20:57:59 +00:00
|
|
|
|
|
|
|
#if defined(_LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB)
|
|
|
|
typedef __base_pointer __link_pointer;
|
|
|
|
#else
|
2022-10-01 13:42:00 +00:00
|
|
|
typedef __conditional_t<is_pointer<_VoidPtr>::value, __base_pointer, __node_pointer> __link_pointer;
|
2015-12-30 20:57:59 +00:00
|
|
|
#endif
|
|
|
|
|
2022-10-01 13:42:00 +00:00
|
|
|
typedef __conditional_t<is_same<__link_pointer, __node_pointer>::value, __base_pointer, __node_pointer>
|
|
|
|
__non_link_pointer;
|
2016-01-04 03:27:52 +00:00
|
|
|
|
|
|
|
static _LIBCPP_HIDE_FROM_ABI __link_pointer __unsafe_link_pointer_cast(__link_pointer __p) { return __p; }
|
|
|
|
|
|
|
|
static _LIBCPP_HIDE_FROM_ABI __link_pointer __unsafe_link_pointer_cast(__non_link_pointer __p) {
|
|
|
|
return static_cast<__link_pointer>(static_cast<_VoidPtr>(__p));
|
|
|
|
}
|
2015-12-30 20:57:59 +00:00
|
|
|
};
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
struct __list_node_base {
|
2015-12-30 20:57:59 +00:00
|
|
|
typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits;
|
|
|
|
typedef typename _NodeTraits::__node_pointer __node_pointer;
|
|
|
|
typedef typename _NodeTraits::__base_pointer __base_pointer;
|
|
|
|
typedef typename _NodeTraits::__link_pointer __link_pointer;
|
2013-06-25 16:08:47 +00:00
|
|
|
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __prev_;
|
|
|
|
__link_pointer __next_;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_node_base()
|
2016-01-04 03:27:52 +00:00
|
|
|
: __prev_(_NodeTraits::__unsafe_link_pointer_cast(__self())),
|
|
|
|
__next_(_NodeTraits::__unsafe_link_pointer_cast(__self())) {}
|
2014-08-05 01:34:12 +00:00
|
|
|
|
2023-10-13 03:13:08 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit __list_node_base(__link_pointer __prev, __link_pointer __next)
|
|
|
|
: __prev_(__prev), __next_(__next) {}
|
|
|
|
|
2015-12-30 20:57:59 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __base_pointer __self() { return pointer_traits<__base_pointer>::pointer_to(*this); }
|
|
|
|
|
2016-01-04 03:27:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __node_pointer __as_node() { return static_cast<__node_pointer>(__self()); }
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
struct __list_node : public __list_node_base<_Tp, _VoidPtr> {
|
2023-10-13 03:13:08 +00:00
|
|
|
// We allow starting the lifetime of nodes without initializing the value held by the node,
|
|
|
|
// since that is handled by the list itself in order to be allocator-aware.
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-10-13 03:13:08 +00:00
|
|
|
private:
|
|
|
|
union {
|
|
|
|
_Tp __value_;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
|
|
|
|
#else
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-10-13 03:13:08 +00:00
|
|
|
private:
|
|
|
|
_ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)];
|
|
|
|
|
|
|
|
public:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); }
|
|
|
|
#endif
|
2016-01-04 03:27:52 +00:00
|
|
|
|
|
|
|
typedef __list_node_base<_Tp, _VoidPtr> __base;
|
|
|
|
typedef typename __base::__link_pointer __link_pointer;
|
|
|
|
|
2023-10-13 03:13:08 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit __list_node(__link_pointer __prev, __link_pointer __next) : __base(__prev, __next) {}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI ~__list_node() {}
|
|
|
|
|
2016-01-04 03:27:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __link_pointer __as_link() { return static_cast<__link_pointer>(__base::__self()); }
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2017-01-04 23:56:00 +00:00
|
|
|
template <class _Tp, class _Alloc = allocator<_Tp> >
|
|
|
|
class _LIBCPP_TEMPLATE_VIS list;
|
2011-06-14 19:58:17 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
class __list_imp;
|
2017-01-04 23:56:00 +00:00
|
|
|
template <class _Tp, class _VoidPtr>
|
|
|
|
class _LIBCPP_TEMPLATE_VIS __list_const_iterator;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _VoidPtr>
|
2017-01-04 23:56:00 +00:00
|
|
|
class _LIBCPP_TEMPLATE_VIS __list_iterator {
|
2015-12-30 20:57:59 +00:00
|
|
|
typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits;
|
|
|
|
typedef typename _NodeTraits::__link_pointer __link_pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __ptr_;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-06-29 21:49:45 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit __list_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) {}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class, class>
|
|
|
|
friend class list;
|
|
|
|
template <class, class>
|
2011-09-27 23:55:03 +00:00
|
|
|
friend class __list_imp;
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class, class>
|
2011-09-27 23:55:03 +00:00
|
|
|
friend class __list_const_iterator;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
typedef bidirectional_iterator_tag iterator_category;
|
|
|
|
typedef _Tp value_type;
|
|
|
|
typedef value_type& reference;
|
2022-09-05 22:33:34 +00:00
|
|
|
typedef __rebind_pointer_t<_VoidPtr, value_type> pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef typename pointer_traits<pointer>::difference_type difference_type;
|
2011-09-27 23:55:03 +00:00
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI reference operator*() const { return __ptr_->__as_node()->__get_value(); }
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI pointer operator->() const {
|
2010-05-11 19:42:16 +00:00
|
|
|
return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__get_value());
|
|
|
|
}
|
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_iterator& operator++() {
|
2011-09-27 23:55:03 +00:00
|
|
|
__ptr_ = __ptr_->__next_;
|
|
|
|
return *this;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_iterator operator++(int) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__list_iterator __t(*this);
|
|
|
|
++(*this);
|
|
|
|
return __t;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_iterator& operator--() {
|
2011-09-27 23:55:03 +00:00
|
|
|
__ptr_ = __ptr_->__prev_;
|
|
|
|
return *this;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_iterator operator--(int) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__list_iterator __t(*this);
|
|
|
|
--(*this);
|
|
|
|
return __t;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __list_iterator& __x, const __list_iterator& __y) {
|
2011-09-27 23:55:03 +00:00
|
|
|
return __x.__ptr_ == __y.__ptr_;
|
|
|
|
}
|
2010-09-22 16:48:34 +00:00
|
|
|
friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __list_iterator& __x, const __list_iterator& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Tp, class _VoidPtr>
|
2017-01-04 23:56:00 +00:00
|
|
|
class _LIBCPP_TEMPLATE_VIS __list_const_iterator {
|
2015-12-30 20:57:59 +00:00
|
|
|
typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits;
|
|
|
|
typedef typename _NodeTraits::__link_pointer __link_pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __ptr_;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-06-29 21:49:45 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit __list_const_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) {}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class, class>
|
|
|
|
friend class list;
|
|
|
|
template <class, class>
|
2011-09-27 23:55:03 +00:00
|
|
|
friend class __list_imp;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
typedef bidirectional_iterator_tag iterator_category;
|
|
|
|
typedef _Tp value_type;
|
|
|
|
typedef const value_type& reference;
|
2022-09-05 22:33:34 +00:00
|
|
|
typedef __rebind_pointer_t<_VoidPtr, const value_type> pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef typename pointer_traits<pointer>::difference_type difference_type;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2013-08-05 21:23:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
|
2013-04-05 17:58:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator(const __list_iterator<_Tp, _VoidPtr>& __p) _NOEXCEPT
|
2011-09-27 23:55:03 +00:00
|
|
|
: __ptr_(__p.__ptr_) {}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference operator*() const { return __ptr_->__as_node()->__get_value(); }
|
2011-09-27 23:55:03 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI pointer operator->() const {
|
2023-10-13 03:13:08 +00:00
|
|
|
return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__get_value());
|
2011-09-27 23:55:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator++() {
|
2023-10-13 03:13:08 +00:00
|
|
|
__ptr_ = __ptr_->__next_;
|
|
|
|
return *this;
|
2011-09-27 23:55:03 +00:00
|
|
|
}
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator operator++(int) {
|
2013-06-25 16:08:47 +00:00
|
|
|
__list_const_iterator __t(*this);
|
2023-10-13 03:13:08 +00:00
|
|
|
++(*this);
|
|
|
|
return __t;
|
2013-06-25 16:08:47 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2011-09-27 23:55:03 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator--() {
|
|
|
|
__ptr_ = __ptr_->__prev_;
|
|
|
|
return *this;
|
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_const_iterator operator--(int) {
|
|
|
|
__list_const_iterator __t(*this);
|
|
|
|
--(*this);
|
|
|
|
return __t;
|
|
|
|
}
|
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __list_const_iterator& __x, const __list_const_iterator& __y) {
|
2011-09-27 23:55:03 +00:00
|
|
|
return __x.__ptr_ == __y.__ptr_;
|
|
|
|
}
|
2010-09-22 16:48:34 +00:00
|
|
|
friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __list_const_iterator& __x, const __list_const_iterator& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
class __list_imp {
|
|
|
|
__list_imp(const __list_imp&);
|
|
|
|
__list_imp& operator=(const __list_imp&);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2018-05-20 14:05:31 +00:00
|
|
|
public:
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef _Alloc allocator_type;
|
|
|
|
typedef allocator_traits<allocator_type> __alloc_traits;
|
|
|
|
typedef typename __alloc_traits::size_type size_type;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2018-05-20 14:05:31 +00:00
|
|
|
protected:
|
|
|
|
typedef _Tp value_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef typename __alloc_traits::void_pointer __void_pointer;
|
|
|
|
typedef __list_iterator<value_type, __void_pointer> iterator;
|
|
|
|
typedef __list_const_iterator<value_type, __void_pointer> const_iterator;
|
|
|
|
typedef __list_node_base<value_type, __void_pointer> __node_base;
|
2023-09-15 14:10:26 +00:00
|
|
|
typedef __list_node<value_type, __void_pointer> __node_type;
|
|
|
|
typedef __rebind_alloc<__alloc_traits, __node_type> __node_allocator;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef allocator_traits<__node_allocator> __node_alloc_traits;
|
|
|
|
typedef typename __node_alloc_traits::pointer __node_pointer;
|
2013-06-25 16:08:47 +00:00
|
|
|
typedef typename __node_alloc_traits::pointer __node_const_pointer;
|
2016-01-04 03:27:52 +00:00
|
|
|
typedef __list_node_pointer_traits<value_type, __void_pointer> __node_pointer_traits;
|
|
|
|
typedef typename __node_pointer_traits::__link_pointer __link_pointer;
|
2015-12-30 20:57:59 +00:00
|
|
|
typedef __link_pointer __link_const_pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef typename __alloc_traits::pointer pointer;
|
|
|
|
typedef typename __alloc_traits::const_pointer const_pointer;
|
|
|
|
typedef typename __alloc_traits::difference_type difference_type;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2022-10-08 20:17:32 +00:00
|
|
|
typedef __rebind_alloc<__alloc_traits, __node_base> __node_base_allocator;
|
2013-06-25 16:08:47 +00:00
|
|
|
typedef typename allocator_traits<__node_base_allocator>::pointer __node_base_pointer;
|
2018-06-05 22:32:52 +00:00
|
|
|
static_assert((!is_same<allocator_type, __node_allocator>::value),
|
|
|
|
"internal allocator type must differ from user-specified "
|
|
|
|
"type; otherwise overload resolution breaks");
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
__node_base __end_;
|
|
|
|
__compressed_pair<size_type, __node_allocator> __size_alloc_;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2016-01-04 03:27:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __link_pointer __end_as_link() const _NOEXCEPT {
|
|
|
|
return __node_pointer_traits::__unsafe_link_pointer_cast(const_cast<__node_base&>(__end_).__self());
|
|
|
|
}
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI size_type& __sz() _NOEXCEPT { return __size_alloc_.first(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const size_type& __sz() const _NOEXCEPT { return __size_alloc_.first(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __size_alloc_.second(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __size_alloc_.second(); }
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2016-11-23 01:18:56 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI size_type __node_alloc_max_size() const _NOEXCEPT {
|
|
|
|
return __node_alloc_traits::max_size(__node_alloc());
|
|
|
|
}
|
2015-12-30 20:57:59 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI static void __unlink_nodes(__link_pointer __f, __link_pointer __l) _NOEXCEPT;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value);
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_imp(const allocator_type& __a);
|
2018-06-05 22:32:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_imp(const __node_allocator& __a);
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __list_imp(__node_allocator&& __a) _NOEXCEPT;
|
2018-06-05 22:32:52 +00:00
|
|
|
#endif
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI ~__list_imp();
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __sz() == 0; }
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-06-29 21:49:45 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__end_.__next_); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__end_.__next_); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_as_link()); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(__end_as_link()); }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void swap(__list_imp& __c)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT;
|
2015-07-13 20:04:56 +00:00
|
|
|
#else
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value);
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c) {
|
|
|
|
__copy_assign_alloc(
|
|
|
|
__c, integral_constant<bool, __node_alloc_traits::propagate_on_container_copy_assignment::value>());
|
2023-09-15 14:10:26 +00:00
|
|
|
}
|
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(!__node_alloc_traits::propagate_on_container_move_assignment::value ||
|
|
|
|
is_nothrow_move_assignable<__node_allocator>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_assign_alloc(
|
|
|
|
__c, integral_constant<bool, __node_alloc_traits::propagate_on_container_move_assignment::value>());
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
|
|
|
|
2023-09-15 14:10:26 +00:00
|
|
|
template <class... _Args>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__link_pointer __prev, __link_pointer __next, _Args&&... __args) {
|
|
|
|
__node_allocator& __alloc = __node_alloc();
|
|
|
|
__allocation_guard<__node_allocator> __guard(__alloc, 1);
|
|
|
|
// Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value
|
2023-10-13 03:13:08 +00:00
|
|
|
// held inside the node, since we need to use the allocator's construct() method for that.
|
2023-12-18 19:01:33 +00:00
|
|
|
//
|
2023-10-13 03:13:08 +00:00
|
|
|
// We don't use the allocator's construct() method to construct the node itself since the
|
|
|
|
// Cpp17FooInsertable named requirements don't require the allocator's construct() method
|
|
|
|
// to work on anything other than the value_type.
|
2023-09-15 14:10:26 +00:00
|
|
|
std::__construct_at(std::addressof(*__guard.__get()), __prev, __next);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-10-13 03:13:08 +00:00
|
|
|
// Now construct the value_type using the allocator's construct() method.
|
|
|
|
__node_alloc_traits::construct(
|
|
|
|
__alloc, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...);
|
2023-09-15 14:10:26 +00:00
|
|
|
return __guard.__release_ptr();
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2023-09-15 14:10:26 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) {
|
2023-10-13 03:13:08 +00:00
|
|
|
// For the same reason as above, we use the allocator's destroy() method for the value_type,
|
|
|
|
// but not for the node itself.
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_allocator& __alloc = __node_alloc();
|
2023-10-13 03:13:08 +00:00
|
|
|
__node_alloc_traits::destroy(__alloc, std::addressof(__node->__get_value()));
|
|
|
|
std::__destroy_at(std::addressof(*__node));
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_alloc_traits::deallocate(__alloc, __node, 1);
|
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
private:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c, true_type) {
|
|
|
|
if (__node_alloc() != __c.__node_alloc())
|
|
|
|
clear();
|
|
|
|
__node_alloc() = __c.__node_alloc();
|
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2016-12-23 23:37:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp&, false_type) {}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2011-09-02 20:42:31 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c, true_type)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {
|
2011-06-30 21:18:19 +00:00
|
|
|
__node_alloc() = std::move(__c.__node_alloc());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2016-12-23 23:37:52 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp&, false_type) _NOEXCEPT {}
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Unlink nodes [__f, __l]
|
|
|
|
template <class _Tp, class _Alloc>
|
2015-12-30 20:57:59 +00:00
|
|
|
inline void __list_imp<_Tp, _Alloc>::__unlink_nodes(__link_pointer __f, __link_pointer __l) _NOEXCEPT {
|
2013-06-25 16:08:47 +00:00
|
|
|
__f->__prev_->__next_ = __l->__next_;
|
|
|
|
__l->__next_->__prev_ = __f->__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2011-06-03 17:30:28 +00:00
|
|
|
inline __list_imp<_Tp, _Alloc>::__list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
|
2019-12-16 23:23:39 +00:00
|
|
|
: __size_alloc_(0, __default_init_tag()) {}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline __list_imp<_Tp, _Alloc>::__list_imp(const allocator_type& __a) : __size_alloc_(0, __node_allocator(__a)) {}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2018-06-05 22:32:52 +00:00
|
|
|
inline __list_imp<_Tp, _Alloc>::__list_imp(const __node_allocator& __a) : __size_alloc_(0, __a) {}
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline __list_imp<_Tp, _Alloc>::__list_imp(__node_allocator&& __a) _NOEXCEPT : __size_alloc_(0, std::move(__a)) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
__list_imp<_Tp, _Alloc>::~__list_imp() {
|
|
|
|
clear();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2011-06-03 17:30:28 +00:00
|
|
|
void __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (!empty()) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __end_.__next_;
|
2016-01-04 03:27:52 +00:00
|
|
|
__link_pointer __l = __end_as_link();
|
2013-06-25 16:08:47 +00:00
|
|
|
__unlink_nodes(__f, __l->__prev_);
|
2010-05-11 19:42:16 +00:00
|
|
|
__sz() = 0;
|
|
|
|
while (__f != __l) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__node_pointer __np = __f->__as_node();
|
2011-09-27 23:55:03 +00:00
|
|
|
__f = __f->__next_;
|
2023-09-15 14:10:26 +00:00
|
|
|
__delete_node(__np);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void __list_imp<_Tp, _Alloc>::swap(__list_imp& __c)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT
|
2015-07-13 20:04:56 +00:00
|
|
|
#else
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value)
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
{
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
|
|
|
|
__alloc_traits::propagate_on_container_swap::value || this->__node_alloc() == __c.__node_alloc(),
|
|
|
|
"list::swap: Either propagate_on_container_swap must be true"
|
|
|
|
" or the allocators must compare equal");
|
2011-06-30 21:18:19 +00:00
|
|
|
using std::swap;
|
2020-11-18 23:54:38 +00:00
|
|
|
std::__swap_allocator(__node_alloc(), __c.__node_alloc());
|
2010-05-11 19:42:16 +00:00
|
|
|
swap(__sz(), __c.__sz());
|
|
|
|
swap(__end_, __c.__end_);
|
|
|
|
if (__sz() == 0)
|
2016-01-04 03:27:52 +00:00
|
|
|
__end_.__next_ = __end_.__prev_ = __end_as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
else
|
2016-01-04 03:27:52 +00:00
|
|
|
__end_.__prev_->__next_ = __end_.__next_->__prev_ = __end_as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__c.__sz() == 0)
|
2016-01-04 03:27:52 +00:00
|
|
|
__c.__end_.__next_ = __c.__end_.__prev_ = __c.__end_as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
else
|
2016-01-04 03:27:52 +00:00
|
|
|
__c.__end_.__prev_->__next_ = __c.__end_.__next_->__prev_ = __c.__end_as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2015-02-18 17:24:08 +00:00
|
|
|
template <class _Tp, class _Alloc /*= allocator<_Tp>*/>
|
2010-05-11 19:42:16 +00:00
|
|
|
class _LIBCPP_TEMPLATE_VIS list : private __list_imp<_Tp, _Alloc> {
|
|
|
|
typedef __list_imp<_Tp, _Alloc> base;
|
2023-09-15 14:10:26 +00:00
|
|
|
typedef typename base::__node_type __node_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
typedef typename base::__node_allocator __node_allocator;
|
|
|
|
typedef typename base::__node_pointer __node_pointer;
|
|
|
|
typedef typename base::__node_alloc_traits __node_alloc_traits;
|
2013-06-25 16:08:47 +00:00
|
|
|
typedef typename base::__node_base __node_base;
|
|
|
|
typedef typename base::__node_base_pointer __node_base_pointer;
|
2015-12-30 20:57:59 +00:00
|
|
|
typedef typename base::__link_pointer __link_pointer;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
public:
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
typedef _Tp value_type;
|
|
|
|
typedef _Alloc allocator_type;
|
2010-05-11 19:42:16 +00:00
|
|
|
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
|
2023-01-20 19:49:55 +00:00
|
|
|
"Allocator::value_type must be same type as value_type");
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
typedef value_type& reference;
|
|
|
|
typedef const value_type& const_reference;
|
|
|
|
typedef typename base::pointer pointer;
|
|
|
|
typedef typename base::const_pointer const_pointer;
|
|
|
|
typedef typename base::size_type size_type;
|
|
|
|
typedef typename base::difference_type difference_type;
|
|
|
|
typedef typename base::iterator iterator;
|
|
|
|
typedef typename base::const_iterator const_iterator;
|
|
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
2023-02-13 23:56:09 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 20
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
typedef size_type __remove_return_type;
|
2019-07-06 06:10:03 +00:00
|
|
|
#else
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
typedef void __remove_return_type;
|
2019-07-06 06:10:03 +00:00
|
|
|
#endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-10-08 20:17:32 +00:00
|
|
|
static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value,
|
|
|
|
"[allocator.requirements] states that rebinding an allocator to the same type should result in the "
|
|
|
|
"original allocator");
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) {}
|
2013-09-08 19:11:51 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit list(const allocator_type& __a) : base(__a) {}
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit list(size_type __n);
|
2023-02-13 23:56:09 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI explicit list(size_type __n, const allocator_type& __a);
|
2013-09-08 19:11:51 +00:00
|
|
|
#endif
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(size_type __n, const value_type& __x);
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
template <class = __enable_if_t<__is_allocator<_Alloc>::value> >
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(size_type __n, const value_type& __x, const allocator_type& __a) : base(__a) {
|
[libcxx][NFC] Make sequence containers slightly more SFINAE-friendly during CTAD.
Disable the constructors taking `(size_type, const value_type&,
allocator_type)` if `allocator_type` is not a valid allocator.
Otherwise, these constructors are considered when resolving e.g.
`(int*, int*, NotAnAllocator())`, leading to a hard error during
instantiation. A hard error makes the Standard's requirement to not
consider deduction guides of the form `(Iterator, Iterator,
BadAllocator)` during overload resolution essentially non-functional.
The previous approach was to SFINAE away `allocator_traits`. This patch
SFINAEs away the specific constructors instead, for consistency with
`basic_string` -- see [LWG3076](wg21.link/lwg3076) which describes
a very similar problem for strings (note, however, that unlike LWG3076,
no valid constructor call is affected by the bad instantiation).
Differential Revision: https://reviews.llvm.org/D114311
2021-12-01 19:55:46 +00:00
|
|
|
for (; __n > 0; --__n)
|
|
|
|
push_back(__x);
|
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _InpIter>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI
|
2023-05-17 17:34:51 +00:00
|
|
|
list(_InpIter __f, _InpIter __l, __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0);
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _InpIter>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
|
|
list(_InpIter __f,
|
|
|
|
_InpIter __l,
|
|
|
|
const allocator_type& __a,
|
2023-05-17 17:34:51 +00:00
|
|
|
__enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI list(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) : base(__a) {
|
|
|
|
prepend_range(std::forward<_Range>(__range));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(const list& __c);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI list(const list& __c, const __type_identity_t<allocator_type>& __a);
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list& operator=(const list& __c);
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(initializer_list<value_type> __il);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI list(initializer_list<value_type> __il, const allocator_type& __a);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(list&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value);
|
2022-03-18 16:49:02 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list(list&& __c, const __type_identity_t<allocator_type>& __a);
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list& operator=(list&& __c)
|
|
|
|
_NOEXCEPT_(__node_alloc_traits::propagate_on_container_move_assignment::value&&
|
|
|
|
is_nothrow_move_assignable<__node_allocator>::value);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI list& operator=(initializer_list<value_type> __il) {
|
|
|
|
assign(__il.begin(), __il.end());
|
|
|
|
return *this;
|
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2017-04-16 03:45:35 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void assign(initializer_list<value_type> __il) { assign(__il.begin(), __il.end()); }
|
2021-04-20 16:03:32 +00:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _InpIter>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void
|
2023-05-17 17:34:51 +00:00
|
|
|
assign(_InpIter __f, _InpIter __l, __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0);
|
2023-07-11 00:16:56 +00:00
|
|
|
|
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void assign_range(_Range&& __range) {
|
|
|
|
__assign_with_sentinel(ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT;
|
2017-04-16 03:45:35 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return base::__sz(); }
|
|
|
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return base::empty(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
|
|
|
|
return std::min<size_type>(base::__node_alloc_max_size(), numeric_limits<difference_type >::max());
|
|
|
|
}
|
|
|
|
|
2011-06-03 17:30:28 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return base::begin(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return base::begin(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return base::end(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return base::end(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return base::begin(); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return base::end(); }
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); }
|
2023-07-11 00:16:56 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return const_reverse_iterator(end()); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return const_reverse_iterator(begin()); }
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference front() {
|
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::front called on empty list");
|
|
|
|
return base::__end_.__next_->__as_node()->__get_value();
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2023-07-11 00:16:56 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reference front() const {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::front called on empty list");
|
2023-07-11 00:16:56 +00:00
|
|
|
return base::__end_.__next_->__as_node()->__get_value();
|
|
|
|
}
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference back() {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::back called on empty list");
|
2023-10-13 03:13:08 +00:00
|
|
|
return base::__end_.__prev_->__as_node()->__get_value();
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI const_reference back() const {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::back called on empty list");
|
2023-07-11 00:16:56 +00:00
|
|
|
return base::__end_.__prev_->__as_node()->__get_value();
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2023-07-11 00:16:56 +00:00
|
|
|
|
2023-02-13 23:56:09 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x);
|
2017-04-16 03:45:35 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void prepend_range(_Range&& __range) {
|
|
|
|
insert_range(begin(), std::forward<_Range>(__range));
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2017-04-16 03:45:35 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
2017-04-16 03:45:35 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void append_range(_Range&& __range) {
|
2023-07-11 00:16:56 +00:00
|
|
|
insert_range(end(), std::forward<_Range>(__range));
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference emplace_front(_Args&&... __args);
|
2023-12-18 19:01:33 +00:00
|
|
|
# else
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args);
|
2023-12-18 19:01:33 +00:00
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI reference emplace_back(_Args&&... __args);
|
2023-12-18 19:01:33 +00:00
|
|
|
# else
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
|
2023-12-18 19:01:33 +00:00
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class... _Args>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __p, _Args&&... __args);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __x);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2017-04-16 03:45:35 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, initializer_list<value_type> __il) {
|
|
|
|
return insert(__p, __il.begin(), __il.end());
|
|
|
|
}
|
2021-04-20 16:03:32 +00:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void push_front(const value_type& __x);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void push_back(const value_type& __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2017-10-17 13:03:17 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
|
|
|
template <class _Arg>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __emplace_back(_Arg&& __arg) {
|
|
|
|
emplace_back(std::forward<_Arg>(__arg));
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __emplace_back(value_type const& __arg) { push_back(__arg); }
|
|
|
|
#endif
|
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __x);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, size_type __n, const value_type& __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _InpIter>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator
|
|
|
|
insert(const_iterator __p,
|
|
|
|
_InpIter __f,
|
|
|
|
_InpIter __l,
|
2023-05-17 17:34:51 +00:00
|
|
|
__enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <_ContainerCompatibleRange<_Tp> _Range>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator insert_range(const_iterator __position, _Range&& __range) {
|
|
|
|
return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-09-22 16:48:34 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void swap(list& __c)
|
2015-07-13 20:04:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT
|
2015-07-13 20:04:56 +00:00
|
|
|
#else
|
Remove exception throwing debug mode handler support.
Summary:
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
I thought that if a debug violation aborted, we could only test one violation per file. This made
it impossible to test debug mode. Which throwing behavior we could test more!
However, the throwing approach didn't work either, since there are debug violations underneath noexcept
functions. This lead to the introduction of `_NOEXCEPT_DEBUG`, which was only noexcept when debug
mode was off.
Having thought more and having grown wiser, `_NOEXCEPT_DEBUG` was a horrible decision. It was
viral, it didn't cover all the cases it needed to, and it was observable to the user -- at worst
changing the behavior of their program.
This patch removes the throwing debug handler, and rewrites the debug tests using 'fork-ing' style
death tests.
Reviewers: mclow.lists, ldionne, thomasanderson
Reviewed By: ldionne
Subscribers: christof, arphaman, libcxx-commits, #libc
Differential Revision: https://reviews.llvm.org/D59166
llvm-svn: 356417
2019-03-18 21:50:12 +00:00
|
|
|
_NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
|
2011-06-03 17:30:28 +00:00
|
|
|
__is_nothrow_swappable<__node_allocator>::value)
|
2015-07-13 20:04:56 +00:00
|
|
|
#endif
|
2011-06-03 17:30:28 +00:00
|
|
|
{
|
|
|
|
base::swap(__c);
|
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { base::clear(); }
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void pop_front();
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void pop_back();
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void resize(size_type __n);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void resize(size_type __n, const value_type& __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c);
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list&& __c) { splice(__p, __c); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list&& __c, const_iterator __i) { splice(__p, __c, __i); }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list&& __c, const_iterator __f, const_iterator __l) {
|
|
|
|
splice(__p, __c, __f, __l);
|
|
|
|
}
|
2017-04-16 03:45:35 +00:00
|
|
|
#endif
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c, const_iterator __i);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __remove_return_type remove(const value_type& __x);
|
|
|
|
template <class _Pred>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __remove_return_type remove_if(_Pred __pred);
|
2022-11-22 08:33:35 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __remove_return_type unique() { return unique(__equal_to()); }
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _BinaryPred>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __remove_return_type unique(_BinaryPred __binary_pred);
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void merge(list& __c);
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void merge(list&& __c) { merge(__c); }
|
2017-04-16 03:45:35 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Comp>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void merge(list&& __c, _Comp __comp) {
|
|
|
|
merge(__c, __comp);
|
|
|
|
}
|
2017-04-16 03:45:35 +00:00
|
|
|
#endif
|
|
|
|
template <class _Comp>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void merge(list& __c, _Comp __comp);
|
2017-04-16 03:45:35 +00:00
|
|
|
|
2016-04-22 01:04:55 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void sort();
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Comp>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void sort(_Comp __comp);
|
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void reverse() _NOEXCEPT;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI bool __invariants() const;
|
2011-09-27 23:55:03 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
private:
|
2023-07-11 00:16:56 +00:00
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __f, _Sentinel __l);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator __insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2015-12-30 20:57:59 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI static void __link_nodes(__link_pointer __p, __link_pointer __f, __link_pointer __l);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __link_nodes_at_front(__link_pointer __f, __link_pointer __l);
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void __link_nodes_at_back(__link_pointer __f, __link_pointer __l);
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI iterator __iterator(size_type __n);
|
|
|
|
// TODO: Make this _LIBCPP_HIDE_FROM_ABI
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Comp>
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDDEN static iterator __sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp);
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __move_assign(list& __c, true_type)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value);
|
2023-01-23 09:27:14 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI void __move_assign(list& __c, false_type);
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2021-08-17 15:59:07 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2018-05-20 14:05:31 +00:00
|
|
|
template <class _InputIterator,
|
2021-03-04 04:02:20 +00:00
|
|
|
class _Alloc = allocator<__iter_value_type<_InputIterator>>,
|
2023-05-17 17:34:51 +00:00
|
|
|
class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
|
[libc++] Use enable_if_t instead of _EnableIf
I just ran into a compiler error involving __bind_back and some overloads
that were being disabled with _EnableIf. I noticed that the error message
was quite bad and did not mention the reason for the overload being
excluded. Specifically, the error looked like this:
candidate template ignored: substitution failure [with _Args =
<ContiguousView>]: no member named '_EnableIfImpl' in 'std::_MetaBase<false>'
Instead, when using enable_if or enable_if_t, the compiler is clever and
can produce better diagnostics, like so:
candidate template ignored: requirement 'is_invocable_v<
std::__bind_back_op<1, std::integer_sequence<unsigned long, 0>>,
std::ranges::views::__transform::__fn &, std::tuple<PlusOne> &,
ContiguousView>' was not satisfied [with _Args = <ContiguousView>]
Basically, it tries to do a poor man's implementation of concepts, which
is already a lot better than simply complaining about substitution failure.
Hence, this commit uses enable_if_t instead of _EnableIf whenever
possible. That is both more straightforward than using the internal
helper, and also leads to better error messages in those cases.
I understand the motivation for _EnableIf's implementation was to improve
compile-time performance, however I believe striving to improve error
messages is even more important for our QOI, hence this patch. Furthermore,
it is unclear that _EnableIf actually improved compile-time performance
in any noticeable way (see discussion in the review for details).
Differential Revision: https://reviews.llvm.org/D108216
2021-08-17 16:26:09 +00:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
2021-03-04 04:02:20 +00:00
|
|
|
list(_InputIterator, _InputIterator) -> list<__iter_value_type<_InputIterator>, _Alloc>;
|
2023-12-18 19:01:33 +00:00
|
|
|
|
2018-05-20 14:05:31 +00:00
|
|
|
template <class _InputIterator,
|
|
|
|
class _Alloc,
|
2023-05-17 17:34:51 +00:00
|
|
|
class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
|
[libc++] Use enable_if_t instead of _EnableIf
I just ran into a compiler error involving __bind_back and some overloads
that were being disabled with _EnableIf. I noticed that the error message
was quite bad and did not mention the reason for the overload being
excluded. Specifically, the error looked like this:
candidate template ignored: substitution failure [with _Args =
<ContiguousView>]: no member named '_EnableIfImpl' in 'std::_MetaBase<false>'
Instead, when using enable_if or enable_if_t, the compiler is clever and
can produce better diagnostics, like so:
candidate template ignored: requirement 'is_invocable_v<
std::__bind_back_op<1, std::integer_sequence<unsigned long, 0>>,
std::ranges::views::__transform::__fn &, std::tuple<PlusOne> &,
ContiguousView>' was not satisfied [with _Args = <ContiguousView>]
Basically, it tries to do a poor man's implementation of concepts, which
is already a lot better than simply complaining about substitution failure.
Hence, this commit uses enable_if_t instead of _EnableIf whenever
possible. That is both more straightforward than using the internal
helper, and also leads to better error messages in those cases.
I understand the motivation for _EnableIf's implementation was to improve
compile-time performance, however I believe striving to improve error
messages is even more important for our QOI, hence this patch. Furthermore,
it is unclear that _EnableIf actually improved compile-time performance
in any noticeable way (see discussion in the review for details).
Differential Revision: https://reviews.llvm.org/D108216
2021-08-17 16:26:09 +00:00
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
2021-03-04 04:02:20 +00:00
|
|
|
list(_InputIterator, _InputIterator, _Alloc) -> list<__iter_value_type<_InputIterator>, _Alloc>;
|
2018-05-20 14:05:31 +00:00
|
|
|
#endif
|
|
|
|
|
2023-07-11 00:16:56 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 23
|
|
|
|
template <ranges::input_range _Range,
|
|
|
|
class _Alloc = allocator<ranges::range_value_t<_Range>>,
|
|
|
|
class = enable_if_t<__is_allocator<_Alloc>::value> >
|
|
|
|
list(from_range_t, _Range&&, _Alloc = _Alloc()) -> list<ranges::range_value_t<_Range>, _Alloc>;
|
|
|
|
#endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
// Link in nodes [__f, __l] just prior to __p
|
|
|
|
template <class _Tp, class _Alloc>
|
2015-12-30 20:57:59 +00:00
|
|
|
inline void list<_Tp, _Alloc>::__link_nodes(__link_pointer __p, __link_pointer __f, __link_pointer __l) {
|
2013-06-25 16:08:47 +00:00
|
|
|
__p->__prev_->__next_ = __f;
|
|
|
|
__f->__prev_ = __p->__prev_;
|
|
|
|
__p->__prev_ = __l;
|
|
|
|
__l->__next_ = __p;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2014-08-05 01:34:12 +00:00
|
|
|
// Link in nodes [__f, __l] at the front of the list
|
|
|
|
template <class _Tp, class _Alloc>
|
2015-12-30 20:57:59 +00:00
|
|
|
inline void list<_Tp, _Alloc>::__link_nodes_at_front(__link_pointer __f, __link_pointer __l) {
|
2016-01-04 03:27:52 +00:00
|
|
|
__f->__prev_ = base::__end_as_link();
|
2014-08-08 15:35:52 +00:00
|
|
|
__l->__next_ = base::__end_.__next_;
|
|
|
|
__l->__next_->__prev_ = __l;
|
|
|
|
base::__end_.__next_ = __f;
|
2014-08-05 01:34:12 +00:00
|
|
|
}
|
|
|
|
|
2018-11-03 17:51:09 +00:00
|
|
|
// Link in nodes [__f, __l] at the back of the list
|
2014-08-05 01:34:12 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
2015-12-30 20:57:59 +00:00
|
|
|
inline void list<_Tp, _Alloc>::__link_nodes_at_back(__link_pointer __f, __link_pointer __l) {
|
2016-01-04 03:27:52 +00:00
|
|
|
__l->__next_ = base::__end_as_link();
|
2014-08-08 15:35:52 +00:00
|
|
|
__f->__prev_ = base::__end_.__prev_;
|
|
|
|
__f->__prev_->__next_ = __f;
|
|
|
|
base::__end_.__prev_ = __l;
|
2014-08-05 01:34:12 +00:00
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::__iterator(size_type __n) {
|
2011-06-30 21:18:19 +00:00
|
|
|
return __n <= base::__sz() / 2 ? std::next(begin(), __n) : std::prev(end(), base::__sz() - __n);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(size_type __n) {
|
|
|
|
for (; __n > 0; --__n)
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
emplace_back();
|
|
|
|
#else
|
|
|
|
push_back(value_type());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-02-13 23:56:09 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 14
|
2013-09-08 19:11:51 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(size_type __n, const allocator_type& __a) : base(__a) {
|
|
|
|
for (; __n > 0; --__n)
|
|
|
|
emplace_back();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(size_type __n, const value_type& __x) {
|
|
|
|
for (; __n > 0; --__n)
|
|
|
|
push_back(__x);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _InpIter>
|
2023-05-17 17:34:51 +00:00
|
|
|
list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) {
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __f != __l; ++__f)
|
2017-10-17 13:03:17 +00:00
|
|
|
__emplace_back(*__f);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _InpIter>
|
|
|
|
list<_Tp, _Alloc>::list(_InpIter __f,
|
|
|
|
_InpIter __l,
|
|
|
|
const allocator_type& __a,
|
2023-05-17 17:34:51 +00:00
|
|
|
__enable_if_t<__has_input_iterator_category<_InpIter>::value>*)
|
2010-05-11 19:42:16 +00:00
|
|
|
: base(__a) {
|
|
|
|
for (; __f != __l; ++__f)
|
2017-10-17 13:03:17 +00:00
|
|
|
__emplace_back(*__f);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(const list& __c)
|
2018-06-05 22:32:52 +00:00
|
|
|
: base(__node_alloc_traits::select_on_container_copy_construction(__c.__node_alloc())) {
|
2010-05-11 19:42:16 +00:00
|
|
|
for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i)
|
|
|
|
push_back(*__i);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2022-03-18 16:49:02 +00:00
|
|
|
list<_Tp, _Alloc>::list(const list& __c, const __type_identity_t<allocator_type>& __a) : base(__a) {
|
2010-05-11 19:42:16 +00:00
|
|
|
for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i)
|
|
|
|
push_back(*__i);
|
|
|
|
}
|
|
|
|
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2011-08-12 21:56:02 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(initializer_list<value_type> __il, const allocator_type& __a) : base(__a) {
|
|
|
|
for (typename initializer_list<value_type>::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i)
|
|
|
|
push_back(*__i);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
list<_Tp, _Alloc>::list(initializer_list<value_type> __il) {
|
|
|
|
for (typename initializer_list<value_type>::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i)
|
|
|
|
push_back(*__i);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2022-01-10 23:33:35 +00:00
|
|
|
inline list<_Tp, _Alloc>::list(list&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value)
|
|
|
|
: base(std::move(__c.__node_alloc())) {
|
2010-05-11 19:42:16 +00:00
|
|
|
splice(end(), __c);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2022-03-18 16:49:02 +00:00
|
|
|
inline list<_Tp, _Alloc>::list(list&& __c, const __type_identity_t<allocator_type>& __a) : base(__a) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__a == __c.get_allocator())
|
|
|
|
splice(end(), __c);
|
|
|
|
else {
|
2011-11-29 18:15:50 +00:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
assign(_Ip(__c.begin()), _Ip(__c.end()));
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(list&& __c)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(__node_alloc_traits::propagate_on_container_move_assignment::value&&
|
|
|
|
is_nothrow_move_assignable<__node_allocator>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__move_assign(__c, integral_constant<bool, __node_alloc_traits::propagate_on_container_move_assignment::value>());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::__move_assign(list& __c, false_type) {
|
|
|
|
if (base::__node_alloc() != __c.__node_alloc()) {
|
2011-11-29 18:15:50 +00:00
|
|
|
typedef move_iterator<iterator> _Ip;
|
|
|
|
assign(_Ip(__c.begin()), _Ip(__c.end()));
|
2010-05-11 19:42:16 +00:00
|
|
|
} else
|
|
|
|
__move_assign(__c, true_type());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::__move_assign(list& __c, true_type)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {
|
2010-05-11 19:42:16 +00:00
|
|
|
clear();
|
|
|
|
base::__move_assign_alloc(__c);
|
|
|
|
splice(end(), __c);
|
|
|
|
}
|
|
|
|
|
2021-04-20 16:03:32 +00:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2017-04-16 03:45:35 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(const list& __c) {
|
2021-09-28 17:15:18 +00:00
|
|
|
if (this != std::addressof(__c)) {
|
2017-04-16 03:45:35 +00:00
|
|
|
base::__copy_assign_alloc(__c);
|
|
|
|
assign(__c.begin(), __c.end());
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _InpIter>
|
|
|
|
void list<_Tp, _Alloc>::assign(
|
2023-05-17 17:34:51 +00:00
|
|
|
_InpIter __f, _InpIter __l, __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) {
|
2023-07-11 00:16:56 +00:00
|
|
|
__assign_with_sentinel(__f, __l);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI void list<_Tp, _Alloc>::__assign_with_sentinel(_Iterator __f, _Sentinel __l) {
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __i = begin();
|
|
|
|
iterator __e = end();
|
2021-09-08 01:35:37 +00:00
|
|
|
for (; __f != __l && __i != __e; ++__f, (void)++__i)
|
2010-05-11 19:42:16 +00:00
|
|
|
*__i = *__f;
|
|
|
|
if (__i == __e)
|
2023-07-11 00:16:56 +00:00
|
|
|
__insert_with_sentinel(__e, std::move(__f), std::move(__l));
|
2010-05-11 19:42:16 +00:00
|
|
|
else
|
|
|
|
erase(__i, __e);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::assign(size_type __n, const value_type& __x) {
|
|
|
|
iterator __i = begin();
|
|
|
|
iterator __e = end();
|
2021-09-08 01:35:37 +00:00
|
|
|
for (; __n > 0 && __i != __e; --__n, (void)++__i)
|
2010-05-11 19:42:16 +00:00
|
|
|
*__i = __x;
|
|
|
|
if (__i == __e)
|
|
|
|
insert(__e, __n, __x);
|
|
|
|
else
|
|
|
|
erase(__i, __e);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2011-06-03 17:30:28 +00:00
|
|
|
inline _Alloc list<_Tp, _Alloc>::get_allocator() const _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
return allocator_type(base::__node_alloc());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, const value_type& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x);
|
|
|
|
__link_nodes(__p.__ptr_, __node->__as_link(), __node->__as_link());
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
2023-09-15 14:10:26 +00:00
|
|
|
return iterator(__node->__as_link());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
typename list<_Tp, _Alloc>::iterator
|
|
|
|
list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& __x) {
|
2023-06-29 21:49:45 +00:00
|
|
|
iterator __r(__p.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__n > 0) {
|
|
|
|
size_type __ds = 0;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
++__ds;
|
2023-09-15 14:10:26 +00:00
|
|
|
__r = iterator(__node->__as_link());
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __e = __r;
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2021-09-08 01:35:37 +00:00
|
|
|
for (--__n; __n != 0; --__n, (void)++__e, ++__ds) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__e.__ptr_->__next_ = this->__create_node(/* prev = */ __e.__ptr_, /* next = */ nullptr, __x)->__as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
while (true) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __prev = __e.__ptr_->__prev_;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __current = __e.__ptr_->__as_node();
|
|
|
|
this->__delete_node(__current);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__prev == 0)
|
|
|
|
break;
|
2023-06-29 21:49:45 +00:00
|
|
|
__e = iterator(__prev);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
throw;
|
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__sz() += __ds;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _InpIter>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(
|
2023-05-17 17:34:51 +00:00
|
|
|
const_iterator __p, _InpIter __f, _InpIter __l, __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) {
|
2023-07-11 00:16:56 +00:00
|
|
|
return __insert_with_sentinel(__p, __f, __l);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI typename list<_Tp, _Alloc>::iterator
|
|
|
|
list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l) {
|
2023-06-29 21:49:45 +00:00
|
|
|
iterator __r(__p.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__f != __l) {
|
|
|
|
size_type __ds = 0;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, *__f);
|
2010-05-11 19:42:16 +00:00
|
|
|
++__ds;
|
2023-09-15 14:10:26 +00:00
|
|
|
__r = iterator(__node->__as_link());
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __e = __r;
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2021-09-08 01:35:37 +00:00
|
|
|
for (++__f; __f != __l; ++__f, (void)++__e, ++__ds) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__e.__ptr_->__next_ = this->__create_node(/* prev = */ __e.__ptr_, /* next = */ nullptr, *__f)->__as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
while (true) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __prev = __e.__ptr_->__prev_;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __current = __e.__ptr_->__as_node();
|
|
|
|
this->__delete_node(__current);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__prev == 0)
|
|
|
|
break;
|
2023-06-29 21:49:45 +00:00
|
|
|
__e = iterator(__prev);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
throw;
|
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__sz() += __ds;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::push_front(const value_type& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x);
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_nodes_at_front(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::push_back(const value_type& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x);
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
|
|
|
__link_nodes_at_back(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
|
|
|
}
|
|
|
|
|
2017-04-16 03:45:35 +00:00
|
|
|
#ifndef _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::push_front(value_type&& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x));
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
|
|
|
__link_nodes_at_front(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::push_back(value_type&& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x));
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
|
|
|
__link_nodes_at_back(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class... _Args>
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2016-07-21 03:20:17 +00:00
|
|
|
typename list<_Tp, _Alloc>::reference
|
2017-01-24 23:09:12 +00:00
|
|
|
# else
|
|
|
|
void
|
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
list<_Tp, _Alloc>::emplace_front(_Args&&... __args) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node =
|
|
|
|
this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...);
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
|
|
|
__link_nodes_at_front(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2023-10-13 03:13:08 +00:00
|
|
|
return __node->__get_value();
|
2017-01-24 23:09:12 +00:00
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class... _Args>
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2016-07-21 03:20:17 +00:00
|
|
|
typename list<_Tp, _Alloc>::reference
|
2017-01-24 23:09:12 +00:00
|
|
|
# else
|
|
|
|
void
|
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
list<_Tp, _Alloc>::emplace_back(_Args&&... __args) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node =
|
|
|
|
this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...);
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_nodes_at_back(__nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
2023-02-13 23:56:09 +00:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
2023-10-13 03:13:08 +00:00
|
|
|
return __node->__get_value();
|
2017-01-24 23:09:12 +00:00
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class... _Args>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::emplace(const_iterator __p, _Args&&... __args) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node =
|
|
|
|
this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...);
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_nodes(__p.__ptr_, __nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
2023-06-29 21:49:45 +00:00
|
|
|
return iterator(__nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x));
|
|
|
|
__link_pointer __nl = __node->__as_link();
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_nodes(__p.__ptr_, __nl, __nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
++base::__sz();
|
2023-06-29 21:49:45 +00:00
|
|
|
return iterator(__nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2021-04-20 16:03:32 +00:00
|
|
|
#endif // _LIBCPP_CXX03_LANG
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::pop_front() {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_front() called with empty list");
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __n = base::__end_.__next_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__n, __n);
|
|
|
|
--base::__sz();
|
2023-09-15 14:10:26 +00:00
|
|
|
this->__delete_node(__n->__as_node());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::pop_back() {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_back() called on an empty list");
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __n = base::__end_.__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__n, __n);
|
|
|
|
--base::__sz();
|
2023-09-15 14:10:26 +00:00
|
|
|
this->__delete_node(__n->__as_node());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __p) {
|
2013-04-05 00:18:49 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(), "list::erase(iterator) called with a non-dereferenceable iterator");
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __n = __p.__ptr_;
|
|
|
|
__link_pointer __r = __n->__next_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__n, __n);
|
|
|
|
--base::__sz();
|
2023-09-15 14:10:26 +00:00
|
|
|
this->__delete_node(__n->__as_node());
|
2023-06-29 21:49:45 +00:00
|
|
|
return iterator(__r);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __f, const_iterator __l) {
|
|
|
|
if (__f != __l) {
|
2013-06-25 16:08:47 +00:00
|
|
|
base::__unlink_nodes(__f.__ptr_, __l.__ptr_->__prev_);
|
2010-05-11 19:42:16 +00:00
|
|
|
while (__f != __l) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __n = __f.__ptr_;
|
2010-05-11 19:42:16 +00:00
|
|
|
++__f;
|
|
|
|
--base::__sz();
|
2023-09-15 14:10:26 +00:00
|
|
|
this->__delete_node(__n->__as_node());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2023-06-29 21:49:45 +00:00
|
|
|
return iterator(__l.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::resize(size_type __n) {
|
|
|
|
if (__n < base::__sz())
|
|
|
|
erase(__iterator(__n), end());
|
|
|
|
else if (__n > base::__sz()) {
|
|
|
|
__n -= base::__sz();
|
|
|
|
size_type __ds = 0;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr);
|
2010-05-11 19:42:16 +00:00
|
|
|
++__ds;
|
2023-09-15 14:10:26 +00:00
|
|
|
iterator __r = iterator(__node->__as_link());
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __e = __r;
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2021-09-08 01:35:37 +00:00
|
|
|
for (--__n; __n != 0; --__n, (void)++__e, ++__ds) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__e.__ptr_->__next_ = this->__create_node(/* prev = */ __e.__ptr_, /* next = */ nullptr)->__as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
while (true) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __prev = __e.__ptr_->__prev_;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __current = __e.__ptr_->__as_node();
|
|
|
|
this->__delete_node(__current);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__prev == 0)
|
|
|
|
break;
|
2023-06-29 21:49:45 +00:00
|
|
|
__e = iterator(__prev);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
throw;
|
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2014-08-05 01:34:12 +00:00
|
|
|
__link_nodes_at_back(__r.__ptr_, __e.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__sz() += __ds;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) {
|
|
|
|
if (__n < base::__sz())
|
|
|
|
erase(__iterator(__n), end());
|
|
|
|
else if (__n > base::__sz()) {
|
|
|
|
__n -= base::__sz();
|
|
|
|
size_type __ds = 0;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x);
|
2010-05-11 19:42:16 +00:00
|
|
|
++__ds;
|
2023-09-15 14:10:26 +00:00
|
|
|
__link_pointer __nl = __node->__as_link();
|
2023-06-29 21:49:45 +00:00
|
|
|
iterator __r = iterator(__nl);
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __e = __r;
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
try {
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2021-09-08 01:35:37 +00:00
|
|
|
for (--__n; __n != 0; --__n, (void)++__e, ++__ds) {
|
2023-09-15 14:10:26 +00:00
|
|
|
__e.__ptr_->__next_ = this->__create_node(/* prev = */ __e.__ptr_, /* next = */ nullptr, __x)->__as_link();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
2010-05-11 19:42:16 +00:00
|
|
|
} catch (...) {
|
|
|
|
while (true) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __prev = __e.__ptr_->__prev_;
|
2023-09-15 14:10:26 +00:00
|
|
|
__node_pointer __current = __e.__ptr_->__as_node();
|
|
|
|
this->__delete_node(__current);
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__prev == 0)
|
|
|
|
break;
|
2023-06-29 21:49:45 +00:00
|
|
|
__e = iterator(__prev);
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
throw;
|
2010-08-22 00:02:43 +00:00
|
|
|
}
|
2023-02-02 10:47:01 +00:00
|
|
|
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
2016-01-04 03:27:52 +00:00
|
|
|
__link_nodes(base::__end_as_link(), __r.__ptr_, __e.__ptr_);
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__sz() += __ds;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c) {
|
2023-07-20 17:13:54 +00:00
|
|
|
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
|
|
|
|
this != std::addressof(__c), "list::splice(iterator, list) called with this == &list");
|
2010-05-11 19:42:16 +00:00
|
|
|
if (!__c.empty()) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __c.__end_.__next_;
|
|
|
|
__link_pointer __l = __c.__end_.__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__f, __l);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__p.__ptr_, __f, __l);
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__sz() += __c.__sz();
|
|
|
|
__c.__sz() = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i) {
|
2011-09-27 23:55:03 +00:00
|
|
|
if (__p.__ptr_ != __i.__ptr_ && __p.__ptr_ != __i.__ptr_->__next_) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __i.__ptr_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__f, __f);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__p.__ptr_, __f, __f);
|
2010-05-11 19:42:16 +00:00
|
|
|
--__c.__sz();
|
|
|
|
++base::__sz();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l) {
|
|
|
|
if (__f != __l) {
|
2018-01-25 00:02:48 +00:00
|
|
|
__link_pointer __first = __f.__ptr_;
|
|
|
|
--__l;
|
|
|
|
__link_pointer __last = __l.__ptr_;
|
2021-10-27 16:50:07 +00:00
|
|
|
if (this != std::addressof(__c)) {
|
2018-01-25 00:02:48 +00:00
|
|
|
size_type __s = std::distance(__f, __l) + 1;
|
2010-05-11 19:42:16 +00:00
|
|
|
__c.__sz() -= __s;
|
|
|
|
base::__sz() += __s;
|
|
|
|
}
|
|
|
|
base::__unlink_nodes(__first, __last);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__p.__ptr_, __first, __last);
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2019-07-06 06:10:03 +00:00
|
|
|
typename list<_Tp, _Alloc>::__remove_return_type list<_Tp, _Alloc>::remove(const value_type& __x) {
|
2016-12-14 22:48:38 +00:00
|
|
|
list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
|
2014-08-08 15:35:52 +00:00
|
|
|
for (const_iterator __i = begin(), __e = end(); __i != __e;) {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (*__i == __x) {
|
2014-08-08 15:35:52 +00:00
|
|
|
const_iterator __j = std::next(__i);
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __j != __e && *__j == __x; ++__j)
|
|
|
|
;
|
2014-08-08 15:35:52 +00:00
|
|
|
__deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j);
|
|
|
|
__i = __j;
|
2014-08-04 17:32:25 +00:00
|
|
|
if (__i != __e)
|
2014-08-05 01:34:12 +00:00
|
|
|
++__i;
|
2010-05-11 19:42:16 +00:00
|
|
|
} else
|
|
|
|
++__i;
|
|
|
|
}
|
2019-07-01 19:22:00 +00:00
|
|
|
|
2019-07-06 06:10:03 +00:00
|
|
|
return (__remove_return_type)__deleted_nodes.size();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Pred>
|
2019-07-06 06:10:03 +00:00
|
|
|
typename list<_Tp, _Alloc>::__remove_return_type list<_Tp, _Alloc>::remove_if(_Pred __pred) {
|
2019-04-16 22:11:26 +00:00
|
|
|
list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
|
2010-05-11 19:42:16 +00:00
|
|
|
for (iterator __i = begin(), __e = end(); __i != __e;) {
|
|
|
|
if (__pred(*__i)) {
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __j = std::next(__i);
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __j != __e && __pred(*__j); ++__j)
|
|
|
|
;
|
2019-04-16 22:11:26 +00:00
|
|
|
__deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j);
|
|
|
|
__i = __j;
|
2014-08-04 17:32:25 +00:00
|
|
|
if (__i != __e)
|
2014-08-05 01:34:12 +00:00
|
|
|
++__i;
|
2010-05-11 19:42:16 +00:00
|
|
|
} else
|
|
|
|
++__i;
|
|
|
|
}
|
|
|
|
|
2019-07-06 06:10:03 +00:00
|
|
|
return (__remove_return_type)__deleted_nodes.size();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _BinaryPred>
|
|
|
|
typename list<_Tp, _Alloc>::__remove_return_type list<_Tp, _Alloc>::unique(_BinaryPred __binary_pred) {
|
2019-04-16 22:11:26 +00:00
|
|
|
list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
|
2010-05-11 19:42:16 +00:00
|
|
|
for (iterator __i = begin(), __e = end(); __i != __e;) {
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __j = std::next(__i);
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __j != __e && __binary_pred(*__i, *__j); ++__j)
|
|
|
|
;
|
2019-04-16 22:11:26 +00:00
|
|
|
if (++__i != __j) {
|
|
|
|
__deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j);
|
|
|
|
__i = __j;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2019-10-23 17:40:15 +00:00
|
|
|
|
2019-07-06 06:10:03 +00:00
|
|
|
return (__remove_return_type)__deleted_nodes.size();
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline void list<_Tp, _Alloc>::merge(list& __c) {
|
2023-06-06 20:57:45 +00:00
|
|
|
merge(__c, __less<>());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Comp>
|
|
|
|
void list<_Tp, _Alloc>::merge(list& __c, _Comp __comp) {
|
2018-09-12 14:46:17 +00:00
|
|
|
if (this != std::addressof(__c)) {
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __f1 = begin();
|
|
|
|
iterator __e1 = end();
|
|
|
|
iterator __f2 = __c.begin();
|
|
|
|
iterator __e2 = __c.end();
|
|
|
|
while (__f1 != __e1 && __f2 != __e2) {
|
|
|
|
if (__comp(*__f2, *__f1)) {
|
|
|
|
size_type __ds = 1;
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __m2 = std::next(__f2);
|
2021-09-08 01:35:37 +00:00
|
|
|
for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2, (void)++__ds)
|
2010-05-11 19:42:16 +00:00
|
|
|
;
|
|
|
|
base::__sz() += __ds;
|
|
|
|
__c.__sz() -= __ds;
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __f2.__ptr_;
|
|
|
|
__link_pointer __l = __m2.__ptr_->__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
__f2 = __m2;
|
|
|
|
base::__unlink_nodes(__f, __l);
|
2011-06-30 21:18:19 +00:00
|
|
|
__m2 = std::next(__f1);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__f1.__ptr_, __f, __l);
|
2010-05-11 19:42:16 +00:00
|
|
|
__f1 = __m2;
|
|
|
|
} else
|
|
|
|
++__f1;
|
|
|
|
}
|
|
|
|
splice(__e1, __c);
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline void list<_Tp, _Alloc>::sort() {
|
2023-06-06 20:57:45 +00:00
|
|
|
sort(__less<>());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Comp>
|
|
|
|
inline void list<_Tp, _Alloc>::sort(_Comp __comp) {
|
|
|
|
__sort(begin(), end(), base::__sz(), __comp);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
template <class _Comp>
|
|
|
|
typename list<_Tp, _Alloc>::iterator
|
|
|
|
list<_Tp, _Alloc>::__sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp) {
|
|
|
|
switch (__n) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
return __f1;
|
|
|
|
case 2:
|
|
|
|
if (__comp(*--__e2, *__f1)) {
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __e2.__ptr_;
|
2010-05-11 19:42:16 +00:00
|
|
|
base::__unlink_nodes(__f, __f);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__f1.__ptr_, __f, __f);
|
2010-05-11 19:42:16 +00:00
|
|
|
return __e2;
|
|
|
|
}
|
|
|
|
return __f1;
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
size_type __n2 = __n / 2;
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __e1 = std::next(__f1, __n2);
|
2010-05-11 19:42:16 +00:00
|
|
|
iterator __r = __f1 = __sort(__f1, __e1, __n2, __comp);
|
|
|
|
iterator __f2 = __e1 = __sort(__e1, __e2, __n - __n2, __comp);
|
|
|
|
if (__comp(*__f2, *__f1)) {
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __m2 = std::next(__f2);
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2)
|
|
|
|
;
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __f2.__ptr_;
|
|
|
|
__link_pointer __l = __m2.__ptr_->__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
__r = __f2;
|
|
|
|
__e1 = __f2 = __m2;
|
|
|
|
base::__unlink_nodes(__f, __l);
|
2011-06-30 21:18:19 +00:00
|
|
|
__m2 = std::next(__f1);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__f1.__ptr_, __f, __l);
|
2010-05-11 19:42:16 +00:00
|
|
|
__f1 = __m2;
|
|
|
|
} else
|
|
|
|
++__f1;
|
|
|
|
while (__f1 != __e1 && __f2 != __e2) {
|
|
|
|
if (__comp(*__f2, *__f1)) {
|
2011-06-30 21:18:19 +00:00
|
|
|
iterator __m2 = std::next(__f2);
|
2010-05-11 19:42:16 +00:00
|
|
|
for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2)
|
|
|
|
;
|
2015-12-30 20:57:59 +00:00
|
|
|
__link_pointer __f = __f2.__ptr_;
|
|
|
|
__link_pointer __l = __m2.__ptr_->__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
if (__e1 == __f2)
|
|
|
|
__e1 = __m2;
|
|
|
|
__f2 = __m2;
|
|
|
|
base::__unlink_nodes(__f, __l);
|
2011-06-30 21:18:19 +00:00
|
|
|
__m2 = std::next(__f1);
|
2013-06-25 16:08:47 +00:00
|
|
|
__link_nodes(__f1.__ptr_, __f, __l);
|
2010-05-11 19:42:16 +00:00
|
|
|
__f1 = __m2;
|
|
|
|
} else
|
|
|
|
++__f1;
|
|
|
|
}
|
|
|
|
return __r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
2011-06-03 17:30:28 +00:00
|
|
|
void list<_Tp, _Alloc>::reverse() _NOEXCEPT {
|
2010-05-11 19:42:16 +00:00
|
|
|
if (base::__sz() > 1) {
|
|
|
|
iterator __e = end();
|
2011-09-27 23:55:03 +00:00
|
|
|
for (iterator __i = begin(); __i.__ptr_ != __e.__ptr_;) {
|
2011-06-30 21:18:19 +00:00
|
|
|
std::swap(__i.__ptr_->__prev_, __i.__ptr_->__next_);
|
2011-09-27 23:55:03 +00:00
|
|
|
__i.__ptr_ = __i.__ptr_->__prev_;
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
2011-06-30 21:18:19 +00:00
|
|
|
std::swap(__e.__ptr_->__prev_, __e.__ptr_->__next_);
|
2023-12-18 19:01:33 +00:00
|
|
|
}
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2011-09-27 23:55:03 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
bool list<_Tp, _Alloc>::__invariants() const {
|
|
|
|
return size() == std::distance(begin(), end());
|
|
|
|
}
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
2011-06-30 21:18:19 +00:00
|
|
|
return __x.size() == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-20 20:27:32 +00:00
|
|
|
#if _LIBCPP_STD_VER <= 17
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
2011-06-30 21:18:19 +00:00
|
|
|
return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
|
|
|
return __y < __x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
|
|
|
return !(__x < __y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) {
|
|
|
|
return !(__y < __x);
|
|
|
|
}
|
|
|
|
|
2022-08-20 20:27:32 +00:00
|
|
|
#else // _LIBCPP_STD_VER <= 17
|
|
|
|
|
2023-05-23 20:03:35 +00:00
|
|
|
template <class _Tp, class _Allocator>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
|
|
|
|
operator<=>(const list<_Tp, _Allocator>& __x, const list<_Tp, _Allocator>& __y) {
|
2022-08-20 20:27:32 +00:00
|
|
|
return std::lexicographical_compare_three_way(
|
2023-03-21 17:05:35 +00:00
|
|
|
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
|
2022-08-20 20:27:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // _LIBCPP_STD_VER <= 17
|
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class _Tp, class _Alloc>
|
|
|
|
inline _LIBCPP_HIDE_FROM_ABI void swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
|
2011-06-03 17:30:28 +00:00
|
|
|
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__x.swap(__y);
|
|
|
|
}
|
|
|
|
|
2023-02-13 23:56:09 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 20
|
2018-12-14 18:49:35 +00:00
|
|
|
template <class _Tp, class _Allocator, class _Predicate>
|
2020-05-02 11:58:03 +00:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI typename list<_Tp, _Allocator>::size_type
|
|
|
|
erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) {
|
|
|
|
return __c.remove_if(__pred);
|
|
|
|
}
|
2018-12-14 18:49:35 +00:00
|
|
|
|
|
|
|
template <class _Tp, class _Allocator, class _Up>
|
2020-05-02 11:58:03 +00:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI typename list<_Tp, _Allocator>::size_type
|
|
|
|
erase(list<_Tp, _Allocator>& __c, const _Up& __v) {
|
|
|
|
return std::erase_if(__c, [&](auto& __elem) { return __elem == __v; });
|
|
|
|
}
|
2021-09-26 13:47:42 +00:00
|
|
|
|
|
|
|
template <>
|
|
|
|
inline constexpr bool __format::__enable_insertable<std::list<char>> = true;
|
|
|
|
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
|
|
|
template <>
|
|
|
|
inline constexpr bool __format::__enable_insertable<std::list<wchar_t>> = true;
|
2018-12-14 18:49:35 +00:00
|
|
|
# endif
|
|
|
|
|
2023-02-13 23:56:09 +00:00
|
|
|
#endif // _LIBCPP_STD_VER >= 20
|
2021-09-26 13:47:42 +00:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
2023-02-13 23:56:09 +00:00
|
|
|
#if _LIBCPP_STD_VER >= 17
|
2022-10-06 20:53:30 +00:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
namespace pmr {
|
|
|
|
template <class _ValueT>
|
2023-03-29 20:48:20 +00:00
|
|
|
using list _LIBCPP_AVAILABILITY_PMR = std::list<_ValueT, polymorphic_allocator<_ValueT>>;
|
2022-10-06 20:53:30 +00:00
|
|
|
} // namespace pmr
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif
|
|
|
|
|
2017-05-31 22:07:49 +00:00
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
|
2022-09-02 15:53:28 +00:00
|
|
|
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
|
|
|
|
# include <algorithm>
|
2022-09-22 19:53:13 +00:00
|
|
|
# include <atomic>
|
2022-11-02 19:27:42 +00:00
|
|
|
# include <concepts>
|
2023-09-15 14:10:26 +00:00
|
|
|
# include <cstdint>
|
2023-01-08 15:47:53 +00:00
|
|
|
# include <cstdlib>
|
2022-09-02 15:53:28 +00:00
|
|
|
# include <functional>
|
2022-09-22 19:53:13 +00:00
|
|
|
# include <iosfwd>
|
2022-09-02 15:53:28 +00:00
|
|
|
# include <iterator>
|
2023-10-29 17:31:37 +00:00
|
|
|
# include <stdexcept>
|
2023-02-12 11:32:36 +00:00
|
|
|
# include <type_traits>
|
2022-09-22 19:53:13 +00:00
|
|
|
# include <typeinfo>
|
2022-09-02 15:53:28 +00:00
|
|
|
#endif
|
|
|
|
|
2021-04-20 16:03:32 +00:00
|
|
|
#endif // _LIBCPP_LIST
|