Add list class
This commit is contained in:
parent
c4d83b0310
commit
b6a8c83e0b
@ -33,7 +33,7 @@ endif()
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "include/rexy/algorithm.hpp" "include/rexy/algorithm.tpp" "include/rexy/utility.hpp" "include/rexy/hash.hpp" "include/rexy/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/expression.hpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.hpp" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/enum_traits.hpp" "include/rexy/storage_for.hpp" "include/rexy/storage_for.tpp" "include/rexy/visitor.hpp" "include/rexy/string_view.hpp" "include/rexy/string_view.tpp" "include/rexy/format.hpp" "include/rexy/format.tpp")
|
set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "include/rexy/algorithm.hpp" "include/rexy/algorithm.tpp" "include/rexy/utility.hpp" "include/rexy/hash.hpp" "include/rexy/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/expression.hpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.hpp" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/enum_traits.hpp" "include/rexy/storage_for.hpp" "include/rexy/storage_for.tpp" "include/rexy/visitor.hpp" "include/rexy/string_view.hpp" "include/rexy/string_view.tpp" "include/rexy/format.hpp" "include/rexy/format.tpp" "include/rexy/list.hpp" "include/rexy/list.tpp")
|
||||||
|
|
||||||
if(BUILD_HEADER_ONLY)
|
if(BUILD_HEADER_ONLY)
|
||||||
set(LIBREXY_BUILT_LIBRARY_HEADERS "")
|
set(LIBREXY_BUILT_LIBRARY_HEADERS "")
|
||||||
|
|||||||
211
include/rexy/list.hpp
Normal file
211
include/rexy/list.hpp
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/**
|
||||||
|
This file is a part of rexy's general purpose library
|
||||||
|
Copyright (C) 2022 rexy712
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REXY_LLIST_HPP
|
||||||
|
#define REXY_LLIST_HPP
|
||||||
|
|
||||||
|
#include <cstddef> //size_t, ptrdiff_t
|
||||||
|
#include "allocator.hpp" //TODO
|
||||||
|
#include "detail/hasallocator.hpp"
|
||||||
|
#include <iterator> //bidirectional_iterator_tag, reverse_iterator
|
||||||
|
#include <memory> //allocator_traits
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility> //pair
|
||||||
|
|
||||||
|
namespace rexy{
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
class list;
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
struct node_base{
|
||||||
|
node_base* next = nullptr;
|
||||||
|
node_base* prev = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct list_iterator;
|
||||||
|
template<class T>
|
||||||
|
struct const_list_iterator;
|
||||||
|
template<class T>
|
||||||
|
struct node;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc = rexy::allocator<T>>
|
||||||
|
class list : protected detail::hasallocator<typename std::allocator_traits<Alloc>::template rebind_alloc<detail::node<T>>>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using node_allocator_type = detail::hasallocator<typename std::allocator_traits<Alloc>::template rebind_alloc<detail::node<T>>>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using allocator_type = Alloc;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using const_pointer = const value_type*;
|
||||||
|
using iterator = detail::list_iterator<T>;
|
||||||
|
using const_iterator = detail::const_list_iterator<T>;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using node = detail::node<T>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::node_base m_sentinel = {&m_sentinel, &m_sentinel};
|
||||||
|
size_type m_size = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr list(void) = default;
|
||||||
|
constexpr explicit list(const allocator_type& alloc);
|
||||||
|
REXY_CPP20_CONSTEXPR list(size_type count, const_reference value = value_type(), const allocator_type& = allocator_type());
|
||||||
|
REXY_CPP20_CONSTEXPR explicit list(size_type count, const allocator_type& alloc = allocator_type());
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR list(InputIt first, InputIt last, const allocator_type& alloc = allocator_type());
|
||||||
|
REXY_CPP20_CONSTEXPR list(const list& other, const allocator_type& alloc = allocator_type());
|
||||||
|
REXY_CPP20_CONSTEXPR list(list&& other, const allocator_type& alloc = allocator_type());
|
||||||
|
REXY_CPP20_CONSTEXPR list(std::initializer_list<value_type> l, const allocator_type& alloc = allocator_type());
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR ~list(void);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR list& operator=(const list& other);
|
||||||
|
REXY_CPP20_CONSTEXPR list& operator=(list&& other);
|
||||||
|
REXY_CPP20_CONSTEXPR list& operator=(std::initializer_list<value_type> l);
|
||||||
|
|
||||||
|
constexpr bool operator==(const list& other)const noexcept;
|
||||||
|
#if __cpp_impl_three_way_comparison
|
||||||
|
constexpr auto operator<=>(const list& other)const noexcept;
|
||||||
|
#else
|
||||||
|
constexpr bool operator!=(const list& other)const noexcept;
|
||||||
|
constexpr bool operator<(const list& other)const noexcept;
|
||||||
|
constexpr bool operator<=(const list& other)const noexcept;
|
||||||
|
constexpr bool operator>(const list& other)const noexcept;
|
||||||
|
constexpr bool operator>=(const list& other)const noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void assign(size_type count, const_reference value);
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR void assign(InputIt first, InputIt last);
|
||||||
|
REXY_CPP20_CONSTEXPR void assign(std::initializer_list<value_type> l);
|
||||||
|
|
||||||
|
constexpr allocator_type get_allocator(void)const noexcept;
|
||||||
|
|
||||||
|
constexpr reference front(void);
|
||||||
|
constexpr const_reference front(void)const;
|
||||||
|
constexpr reference back(void);
|
||||||
|
constexpr const_reference back(void)const;
|
||||||
|
|
||||||
|
constexpr iterator begin(void)noexcept;
|
||||||
|
constexpr const_iterator begin(void)const noexcept;
|
||||||
|
constexpr const_iterator cbegin(void)const noexcept;
|
||||||
|
constexpr iterator end(void)noexcept;
|
||||||
|
constexpr const_iterator end(void)const noexcept;
|
||||||
|
constexpr const_iterator cend(void)const noexcept;
|
||||||
|
|
||||||
|
constexpr iterator next(iterator i)noexcept;
|
||||||
|
constexpr const_iterator next(const_iterator i)noexcept;
|
||||||
|
|
||||||
|
constexpr iterator prev(iterator i)noexcept;
|
||||||
|
constexpr const_iterator prev(const_iterator i)noexcept;
|
||||||
|
|
||||||
|
constexpr reverse_iterator rbegin(void)noexcept;
|
||||||
|
constexpr const_reverse_iterator rbegin(void)const noexcept;
|
||||||
|
constexpr const_reverse_iterator crbegin(void)const noexcept;
|
||||||
|
constexpr reverse_iterator rend(void)noexcept;
|
||||||
|
constexpr const_reverse_iterator rend(void)const noexcept;
|
||||||
|
constexpr const_reverse_iterator crend(void)const noexcept;
|
||||||
|
|
||||||
|
constexpr bool empty(void)const noexcept;
|
||||||
|
constexpr size_type size(void)const noexcept;
|
||||||
|
constexpr size_type max_size(void)const noexcept;
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void clear(void)noexcept;
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, const_reference value);
|
||||||
|
REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, value_type&& value);
|
||||||
|
REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, size_type count, const_reference value);
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, InputIt first, InputIt last);
|
||||||
|
REXY_CPP20_CONSTEXPR iterator insert(const_iterator pos, std::initializer_list<value_type> l);
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR iterator emplace(const_iterator pos, Args&&... args);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR iterator erase(const_iterator pos);
|
||||||
|
REXY_CPP20_CONSTEXPR iterator erase(const_iterator first, const_iterator last);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR reference push_back(const_reference value);
|
||||||
|
REXY_CPP20_CONSTEXPR reference push_back(value_type&& value);
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR reference emplace_back(Args&&... args);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void pop_back(void);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR reference push_front(const_reference value);
|
||||||
|
REXY_CPP20_CONSTEXPR reference push_front(value_type&& value);
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR reference emplace_front(Args&&... args);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void pop_front(void);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void resize(size_type count);
|
||||||
|
REXY_CPP20_CONSTEXPR void resize(size_type count, value_type value);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void swap(list& other);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void merge(list&& other);
|
||||||
|
template<class Comp>
|
||||||
|
REXY_CPP20_CONSTEXPR void merge(list&& other, Comp comp);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other);
|
||||||
|
REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other, const_iterator it);
|
||||||
|
REXY_CPP20_CONSTEXPR void splice(const_iterator pos, list&& other, const_iterator first, const_iterator last);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR size_type remove(const_reference value);
|
||||||
|
template<class UnaryPred>
|
||||||
|
REXY_CPP20_CONSTEXPR size_type remove_if(UnaryPred p);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void reverse(void)noexcept;
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR size_type unique(void);
|
||||||
|
template<class BinaryPred>
|
||||||
|
REXY_CPP20_CONSTEXPR size_type unique(BinaryPred p);
|
||||||
|
|
||||||
|
REXY_CPP20_CONSTEXPR void sort(void);
|
||||||
|
template<class Comp>
|
||||||
|
REXY_CPP20_CONSTEXPR void sort(Comp comp);
|
||||||
|
private:
|
||||||
|
template<class Comp>
|
||||||
|
iterator mergesort(iterator first, size_type firstlen, Comp comp);
|
||||||
|
std::pair<iterator,size_type> ms_split(iterator it, size_type len);
|
||||||
|
|
||||||
|
static void insert_node_(detail::node_base* prev, detail::node_base* n);
|
||||||
|
static void remove_node_(detail::node_base* rm);
|
||||||
|
static detail::node_base* get_next_then_move_node_(detail::node_base* dest, detail::node_base* n);
|
||||||
|
constexpr auto& sentinel(void){return this->m_sentinel;}
|
||||||
|
constexpr const auto& sentinel(void)const{return this->m_sentinel;}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "list.tpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
657
include/rexy/list.tpp
Normal file
657
include/rexy/list.tpp
Normal file
@ -0,0 +1,657 @@
|
|||||||
|
/**
|
||||||
|
This file is a part of rexy's general purpose library
|
||||||
|
Copyright (C) 2022 rexy712
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REXY_LLIST_TPP
|
||||||
|
#define REXY_LLIST_TPP
|
||||||
|
|
||||||
|
#include <utility> //move, swap, forward
|
||||||
|
#include <limits> //numeric_limits
|
||||||
|
#include <algorithm> //lexicographical_compare_three_way, equal
|
||||||
|
#include <memory> //construct_at, destroy_at
|
||||||
|
|
||||||
|
#include "utility.hpp" //sized_constant_iterator
|
||||||
|
|
||||||
|
namespace rexy{
|
||||||
|
|
||||||
|
namespace detail{
|
||||||
|
template<class T>
|
||||||
|
struct node : public node_base{
|
||||||
|
T data;
|
||||||
|
|
||||||
|
node* next(void)const{return static_cast<node*>(node_base::next);}
|
||||||
|
node* prev(void)const{return static_cast<node*>(node_base::prev);}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct list_iterator{
|
||||||
|
|
||||||
|
using value_type = T;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using const_pointer = const value_type*;
|
||||||
|
|
||||||
|
using node_t = node<T>;
|
||||||
|
|
||||||
|
node_base* current = nullptr;
|
||||||
|
|
||||||
|
constexpr bool operator==(const list_iterator& other)const noexcept{return current == other.current;}
|
||||||
|
constexpr bool operator!=(const list_iterator& other)const noexcept{return current != other.current;}
|
||||||
|
constexpr bool operator==(const const_list_iterator<T>& other)const noexcept{return current == other.nod();}
|
||||||
|
constexpr bool operator!=(const const_list_iterator<T>& other)const noexcept{return current != other.nod();}
|
||||||
|
|
||||||
|
constexpr reference operator*(void){return static_cast<node_t*>(current)->data;}
|
||||||
|
constexpr const_reference operator*(void)const{return static_cast<const node_t*>(current)->data;}
|
||||||
|
constexpr pointer operator->(void){return &(static_cast<node_t*>(current)->data);}
|
||||||
|
constexpr const_pointer operator->(void)const{return &(static_cast<const node_t*>(current)->data);}
|
||||||
|
constexpr list_iterator& operator++(void){
|
||||||
|
current = current->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr list_iterator operator++(int){
|
||||||
|
list_iterator copy(*this);
|
||||||
|
++(*this);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
constexpr list_iterator& operator--(void){
|
||||||
|
current = current->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr list_iterator operator--(int){
|
||||||
|
list_iterator copy(*this);
|
||||||
|
--(*this);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr operator const_list_iterator<T>(void)const{
|
||||||
|
return const_list_iterator<T>{current};
|
||||||
|
}
|
||||||
|
|
||||||
|
list_iterator next(void)const{
|
||||||
|
return list_iterator{current->next};
|
||||||
|
}
|
||||||
|
list_iterator prev(void)const{
|
||||||
|
return list_iterator{current->prev};
|
||||||
|
}
|
||||||
|
|
||||||
|
node_base* nod(void){return current;}
|
||||||
|
node_base* nod(void)const{return current;}
|
||||||
|
};
|
||||||
|
template<class T>
|
||||||
|
struct const_list_iterator{
|
||||||
|
template<class U, class Alloc>
|
||||||
|
friend class rexy::list;
|
||||||
|
|
||||||
|
using value_type = T;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using const_pointer = const value_type*;
|
||||||
|
|
||||||
|
using node_t = node<T>;
|
||||||
|
|
||||||
|
const node_base* current = nullptr;
|
||||||
|
|
||||||
|
constexpr bool operator==(const const_list_iterator& other)const noexcept{return current == other.current;}
|
||||||
|
constexpr bool operator!=(const const_list_iterator& other)const noexcept{return current != other.current;}
|
||||||
|
constexpr bool operator==(const list_iterator<T>& other)const noexcept{return current == other.nod();}
|
||||||
|
constexpr bool operator!=(const list_iterator<T>& other)const noexcept{return current != other.nod();}
|
||||||
|
|
||||||
|
constexpr const_reference operator*(void){return static_cast<const node_t*>(current)->data;}
|
||||||
|
constexpr const_reference operator*(void)const{return static_cast<const node_t*>(current)->data;}
|
||||||
|
constexpr const_pointer operator->(void){return &(static_cast<const node_t*>(current)->data);}
|
||||||
|
constexpr const_pointer operator->(void)const{return &(static_cast<const node_t*>(current)->data);}
|
||||||
|
constexpr const_list_iterator& operator++(void){
|
||||||
|
current = current->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr const_list_iterator operator++(int){
|
||||||
|
const_list_iterator copy(*this);
|
||||||
|
++(*this);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
constexpr const_list_iterator& operator--(void){
|
||||||
|
current = current->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr const_list_iterator operator--(int){
|
||||||
|
const_list_iterator copy(*this);
|
||||||
|
--(*this);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_list_iterator next(void)const{
|
||||||
|
return const_list_iterator{current->next};
|
||||||
|
}
|
||||||
|
const_list_iterator prev(void)const{
|
||||||
|
return const_list_iterator{current->prev};
|
||||||
|
}
|
||||||
|
|
||||||
|
const node_base* nod(void)const{return current;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
list_iterator<T> unconst(void){
|
||||||
|
return list_iterator<T>{const_cast<node_base*>(current)};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
namespace detail{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr list<T,Alloc>::list(const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc){}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(size_type count, const_reference value, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
assign(count, value);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(size_type count, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
assign(count, value_type());
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(InputIt first, InputIt last, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
assign(first, last);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(const list& other, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
assign(other.begin(), other.end());
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(list&& other, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
swap(other);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::list(std::initializer_list<value_type> l, const allocator_type& alloc):
|
||||||
|
node_allocator_type(alloc)
|
||||||
|
{
|
||||||
|
assign(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR list<T,Alloc>::~list(void){
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::operator=(const list& other) -> list&{
|
||||||
|
return (*this = list(other));
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::operator=(list&& other) -> list&{
|
||||||
|
swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::operator=(std::initializer_list<value_type> l) -> list&{
|
||||||
|
return (*this = list(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator==(const list& other)const noexcept{
|
||||||
|
if(m_size != other.m_size)
|
||||||
|
return false;
|
||||||
|
return std::equal(cbegin(), cend(), other.cbegin());
|
||||||
|
}
|
||||||
|
#if __cpp_impl_three_way_comparison
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::operator<=>(const list& other)const noexcept{
|
||||||
|
return std::lexicographical_compare_three_way(cbegin(), cend(), other.cbegin(), other.cend());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator!=(const list& other)const noexcept{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator<(const list& other)const noexcept{
|
||||||
|
return std::lexicographical_compare(cbegin(), cend(), other.cbegin(), other.cend());
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator<=(const list& other)const noexcept{
|
||||||
|
return !(other < *this);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator>(const list& other)const noexcept{
|
||||||
|
return other < *this;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::operator>=(const list& other)const noexcept{
|
||||||
|
return !(*this < other);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::assign(size_type count, const_reference value){
|
||||||
|
assign(sized_constant_iterator{value, count}, sized_constant_iterator<value_type>{{}, 0});
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::assign(InputIt first, InputIt last){
|
||||||
|
auto current = begin();
|
||||||
|
size_type i = 0;
|
||||||
|
for(;i < m_size && first != last;++i){
|
||||||
|
*current++ = *first++;
|
||||||
|
}
|
||||||
|
if(first != last){
|
||||||
|
m_size = i;
|
||||||
|
while(first != last){
|
||||||
|
current = ++(insert(current, *first++));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
erase(current, end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::assign(std::initializer_list<value_type> l){
|
||||||
|
assign(l.begin(), l.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::get_allocator(void)const noexcept -> allocator_type{return {*this};}
|
||||||
|
|
||||||
|
//Direct accessors
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::front(void) -> reference{return *begin();}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::front(void)const -> const_reference{return *begin();}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::back(void) -> reference{return *(--end());}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::back(void)const -> const_reference{return *(--end());}
|
||||||
|
|
||||||
|
//Iterators
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::begin(void)noexcept -> iterator{return iterator{m_sentinel.next};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::begin(void)const noexcept -> const_iterator{return const_iterator{m_sentinel.next};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::cbegin(void)const noexcept -> const_iterator{return const_iterator{m_sentinel.next};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::end(void)noexcept -> iterator{return iterator{&m_sentinel};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::end(void)const noexcept -> const_iterator{return const_iterator{&m_sentinel};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::cend(void)const noexcept -> const_iterator{return const_iterator{&m_sentinel};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::next(iterator i)noexcept -> iterator{
|
||||||
|
return i.next();
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::next(const_iterator i)noexcept -> const_iterator{return i.next();}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::prev(iterator i)noexcept -> iterator{return i.prev();}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::prev(const_iterator i)noexcept -> const_iterator{return i.prev();}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::rbegin(void)noexcept -> reverse_iterator{return reverse_iterator{end()};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::rbegin(void)const noexcept -> const_reverse_iterator{return const_reverse_iterator{end()};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::crbegin(void)const noexcept -> const_reverse_iterator{return const_reverse_iterator{end()};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::rend(void)noexcept -> reverse_iterator{return reverse_iterator{begin()};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::rend(void)const noexcept -> const_reverse_iterator{return const_reverse_iterator{begin()};}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::crend(void)const noexcept -> const_reverse_iterator{return const_reverse_iterator{begin()};}
|
||||||
|
|
||||||
|
//Queries
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr bool list<T,Alloc>::empty(void)const noexcept{return m_sentinel.next == nullptr;}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::size(void)const noexcept -> size_type{return m_size;}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
constexpr auto list<T,Alloc>::max_size(void)const noexcept -> size_type{return std::numeric_limits<difference_type>::max();}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::clear(void)noexcept{
|
||||||
|
erase(begin(), end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::insert(const_iterator pos, const_reference value) -> iterator{
|
||||||
|
return insert(pos, value_type{value});
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::insert(const_iterator pos, value_type&& value) -> iterator{
|
||||||
|
auto* prev = (--pos).unconst().nod();
|
||||||
|
auto* next = prev->next;
|
||||||
|
prev->next = this->allocate(1);
|
||||||
|
next->prev = prev->next;
|
||||||
|
#ifdef __clang__
|
||||||
|
//clang won't let construct at emplace without creating a temporary here...
|
||||||
|
std::construct_at(static_cast<node*>(prev->next), node{{next, prev}, std::move(value)});
|
||||||
|
#else
|
||||||
|
std::construct_at(static_cast<node*>(prev->next), detail::node_base{next, prev}, std::move(value));
|
||||||
|
#endif
|
||||||
|
++m_size;
|
||||||
|
return iterator{prev->next};
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::insert(const_iterator pos, size_type count, const_reference value) -> iterator{
|
||||||
|
auto start = pos.unconst();
|
||||||
|
for(auto i = count;i > 0;--i){
|
||||||
|
pos = ++(insert(pos, value_type{value}));
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class InputIt>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::insert(const_iterator pos, InputIt first, InputIt last) -> iterator{
|
||||||
|
auto start = pos.unconst();
|
||||||
|
while(first != last){
|
||||||
|
pos = ++(insert(pos, *first++));
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::insert(const_iterator pos, std::initializer_list<value_type> l) -> iterator{
|
||||||
|
return insert(pos, l.begin(), l.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::emplace(const_iterator pos, Args&&... args) -> iterator{
|
||||||
|
auto* prev = (--pos).unconst().nod();
|
||||||
|
auto* next = prev->next;
|
||||||
|
prev->next = this->allocate(1);
|
||||||
|
next->prev = prev->next;
|
||||||
|
#ifdef __clang__
|
||||||
|
std::construct_at(static_cast<node*>(prev->next), node{{next, prev}, value_type{std::forward<Args>(args)...}});
|
||||||
|
#else
|
||||||
|
std::construct_at(static_cast<node*>(prev->next), detail::node_base{next, prev}, value_type{std::forward<Args>(args)...});
|
||||||
|
#endif
|
||||||
|
++m_size;
|
||||||
|
return iterator{prev->next};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::erase(const_iterator pos) -> iterator{
|
||||||
|
auto* n = pos.unconst().nod();
|
||||||
|
auto* next = n->next;
|
||||||
|
|
||||||
|
remove_node_(n);
|
||||||
|
std::destroy_at(static_cast<node*>(n));
|
||||||
|
this->deallocate(static_cast<node*>(n), 1);
|
||||||
|
--m_size;
|
||||||
|
return iterator{next};
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::erase(const_iterator first, const_iterator last) -> iterator{
|
||||||
|
while(first != last){
|
||||||
|
first = erase(first);
|
||||||
|
}
|
||||||
|
return last.unconst();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_back(const_reference value) -> reference{
|
||||||
|
return insert(cend(), value);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_back(value_type&& value) -> reference{
|
||||||
|
return insert(cend(), std::move(value));
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::emplace_back(Args&&... args) -> reference{
|
||||||
|
return emplace(cend(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::pop_back(void){
|
||||||
|
erase(--cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_front(const_reference value) -> reference{
|
||||||
|
return insert(cbegin(), value);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::push_front(value_type&& value) -> reference{
|
||||||
|
return insert(cbegin(), std::move(value));
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class... Args>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::emplace_front(Args&&... args) -> reference{
|
||||||
|
return emplace(cbegin(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::pop_front(void){
|
||||||
|
erase(cbegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::resize(size_type count){
|
||||||
|
resize(count, value_type{});
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::resize(size_type count, value_type value){
|
||||||
|
while(count > m_size){
|
||||||
|
insert(cend(), value);
|
||||||
|
}
|
||||||
|
while(m_size > count){
|
||||||
|
erase(--cend());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::swap(list& other){
|
||||||
|
std::swap(m_sentinel, other.m_sentinel);
|
||||||
|
std::swap(m_size, other.m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::merge(list&& other){
|
||||||
|
merge(std::move(other), [](const_reference a, const_reference b){return a < b;});
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class Comp>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::merge(list&& other, Comp comp){
|
||||||
|
if(&other == this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto it = begin();
|
||||||
|
auto oit = other.begin();
|
||||||
|
|
||||||
|
while(it != end() && oit != other.end()){
|
||||||
|
if(comp(*oit, *it)){
|
||||||
|
oit = iterator{get_next_then_move_node_(it.prev().nod(), oit.nod())};
|
||||||
|
++m_size;
|
||||||
|
}else{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
splice(it, std::move(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::splice(const_iterator pos, list&& other){
|
||||||
|
splice(pos, std::move(other), other.begin(), other.end());
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::splice(const_iterator pos, list&& other, const_iterator it){
|
||||||
|
auto oit = it.unconst();
|
||||||
|
auto prev = (--pos).unconst();
|
||||||
|
remove_node_(oit.nod());
|
||||||
|
insert_node_(prev.nod(), oit.nod());
|
||||||
|
|
||||||
|
++m_size;
|
||||||
|
--other.m_size;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::splice(const_iterator pos, list&& other, const_iterator first, const_iterator last){
|
||||||
|
for(auto oit = first;oit != last;){
|
||||||
|
auto onext = oit.next();
|
||||||
|
splice(pos, std::move(other), oit);
|
||||||
|
oit = onext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::remove(const_reference value) -> size_type{
|
||||||
|
return remove_if(
|
||||||
|
[&value](const_reference r) -> bool{
|
||||||
|
return r == value;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class UnaryPred>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::remove_if(UnaryPred pred) -> size_type{
|
||||||
|
size_type count = 0;
|
||||||
|
for(auto it = begin();it != end();){
|
||||||
|
if(pred(*it)){
|
||||||
|
it = erase(it);
|
||||||
|
++count;
|
||||||
|
}else{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::reverse(void)noexcept{
|
||||||
|
auto* it = begin().nod();
|
||||||
|
std::swap(m_sentinel.next, m_sentinel.prev);
|
||||||
|
|
||||||
|
for(;it != &m_sentinel;it = it->prev){
|
||||||
|
std::swap(it->next, it->prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::unique(void) -> size_type{
|
||||||
|
return unique(
|
||||||
|
[](const_reference first, const_reference second) -> bool{
|
||||||
|
return first == second;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class BinaryPred>
|
||||||
|
REXY_CPP20_CONSTEXPR auto list<T,Alloc>::unique(BinaryPred pred) -> size_type{
|
||||||
|
size_type count = 0;
|
||||||
|
for(auto it = begin();it != end();++it){
|
||||||
|
auto next = it.next();
|
||||||
|
while(next != end() && pred(*it, *next)){
|
||||||
|
next = erase(next);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::sort(void){
|
||||||
|
mergesort(begin(), m_size, [](const_reference first, const_reference second)->bool{
|
||||||
|
return first < second;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class Comp>
|
||||||
|
REXY_CPP20_CONSTEXPR void list<T,Alloc>::sort(Comp comp){
|
||||||
|
mergesort(begin(), m_size, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
template<class Comp>
|
||||||
|
auto list<T,Alloc>::mergesort(iterator first, size_type firstlen, Comp comp) -> iterator{
|
||||||
|
if(firstlen == 1)
|
||||||
|
return first;
|
||||||
|
auto [second, secondlen] = ms_split(first, firstlen);
|
||||||
|
firstlen -= secondlen;
|
||||||
|
|
||||||
|
first = mergesort(first, firstlen, comp);
|
||||||
|
second = mergesort(second, secondlen, comp);
|
||||||
|
|
||||||
|
iterator result = first;
|
||||||
|
|
||||||
|
//do this outside the loop to save return value
|
||||||
|
if(comp(*second, *first)){
|
||||||
|
result = second;
|
||||||
|
second = iterator{get_next_then_move_node_(first.prev().nod(), second.nod())};
|
||||||
|
--secondlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(firstlen > 0 && secondlen > 0){
|
||||||
|
if(comp(*second, *first)){
|
||||||
|
second = iterator{get_next_then_move_node_(first.prev().nod(), second.nod())};
|
||||||
|
--secondlen;
|
||||||
|
}else{
|
||||||
|
++first;
|
||||||
|
--firstlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//finish off the second list if it isn't already done
|
||||||
|
while(secondlen > 0){
|
||||||
|
second = iterator{get_next_then_move_node_(first.prev().nod(), second.nod())};
|
||||||
|
--secondlen;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
auto list<T,Alloc>::ms_split(iterator it, size_type len) -> std::pair<iterator,size_type>{
|
||||||
|
size_type second_half_len = len / 2;
|
||||||
|
size_type dist = len - second_half_len;
|
||||||
|
for(auto i = dist;i > 0;--i){
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return {it, second_half_len};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class Alloc>
|
||||||
|
void list<T,Alloc>::insert_node_(detail::node_base* prev, detail::node_base* n){
|
||||||
|
n->next = prev->next;
|
||||||
|
n->prev = prev;
|
||||||
|
prev->next->prev = n;
|
||||||
|
prev->next = n;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
void list<T,Alloc>::remove_node_(detail::node_base* rm){
|
||||||
|
rm->prev->next = rm->next;
|
||||||
|
rm->next->prev = rm->prev;
|
||||||
|
}
|
||||||
|
template<class T, class Alloc>
|
||||||
|
detail::node_base* list<T,Alloc>::get_next_then_move_node_(detail::node_base* dest, detail::node_base* n){
|
||||||
|
auto* next = n->next;
|
||||||
|
remove_node_(n);
|
||||||
|
insert_node_(dest, n);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -22,6 +22,8 @@
|
|||||||
#include "rexy/visitor.hpp"
|
#include "rexy/visitor.hpp"
|
||||||
#include "rexy/string_view.hpp"
|
#include "rexy/string_view.hpp"
|
||||||
#include "rexy/string_view.tpp"
|
#include "rexy/string_view.tpp"
|
||||||
|
#include "rexy/list.hpp"
|
||||||
|
#include "rexy/list.tpp"
|
||||||
|
|
||||||
#ifndef LIBREXY_HEADER_ONLY
|
#ifndef LIBREXY_HEADER_ONLY
|
||||||
#include "rexy/filerd.hpp"
|
#include "rexy/filerd.hpp"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user