// // intrusive_list.tpp.h // intrusive_list // // Created by Sam Jaffe on 1/7/17. // #pragma once template constexpr intrusive_list::intrusive_list( node_type T::*node ) : node_(node) { } template intrusive_list::intrusive_list( std::initializer_list ilist, node_type T::*node ) : node_(node) { assign(ilist); } template intrusive_list::~intrusive_list() { clear(); } template intrusive_list& intrusive_list::operator=( intrusive_list&& other ) { if ( this == & other ) return *this; clear(); // other than this, default node_ = other.node_; size_ = other.size_; head_ = other.head_; other.head_ = &other.end_; } template inline intrusive_list& intrusive_list::operator=( std::initializer_list ilist ) { assign(ilist); } template void intrusive_list::assign( std::initializer_list ilist ) { clear(); for (pointer p : ilist) { push_back(p); } } template inline auto intrusive_list::front() -> reference { return *begin(); } template inline auto intrusive_list::front() const -> const_reference { return *begin(); } template inline auto intrusive_list::back() -> reference { return *--end(); } template inline auto intrusive_list::back() const -> const_reference { return *--end(); } template inline auto intrusive_list::begin() noexcept -> iterator { return iterator{head_}; } template inline auto intrusive_list::begin() const noexcept -> const_iterator { return const_iterator{head_}; } template inline auto intrusive_list::cbegin() const noexcept -> const_iterator { return const_iterator{head_}; } template inline auto intrusive_list::end() noexcept -> iterator { return iterator{tail_}; } template inline auto intrusive_list::end() const noexcept -> const_iterator { return const_iterator{tail_}; } template inline auto intrusive_list::cend() const noexcept -> const_iterator { return const_iterator{tail_}; } template inline auto intrusive_list::rbegin() -> reverse_iterator { return reverse_iterator{end()}; } template inline auto intrusive_list::rbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator{end()}; } template inline auto intrusive_list::crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator{cend()}; } template inline auto intrusive_list::rend() noexcept -> reverse_iterator { return reverse_iterator{begin()}; } template inline auto intrusive_list::rend() const noexcept -> const_reverse_iterator { return const_reverse_iterator{begin()}; } template inline auto intrusive_list::crend() const noexcept -> const_reverse_iterator { return const_reverse_iterator{cbegin()}; } template inline bool intrusive_list::empty() const noexcept { return size() == 0; } template inline auto intrusive_list::size() const noexcept -> size_type { return size_; } template inline auto intrusive_list::max_size() const noexcept -> size_type { return std::numeric_limits::max(); } template inline void intrusive_list::clear() noexcept { erase(begin(), end()); } template auto intrusive_list::insert(const_iterator pos, pointer value) -> iterator { node_type* n = &(value->*node_); if ( n->list_ == nullptr ) { insert_impl( pos, n ); } else { throw std::logic_error{ "cannot use intrusive_list::insert to perform a splice" }; } return iterator{n}; } template auto intrusive_list::transfer(const_iterator pos, pointer value) -> iterator { node_type* n = &(value->*node_); n->unlink( ); insert_impl( pos, n ); return iterator{n}; } template void intrusive_list::insert_impl( const_iterator pos, node_type * n ) { link(pos.get()->prev_, n); link(n, pos.get()); n->list_ = this; ++size_; } template auto intrusive_list::insert(const_iterator pos, std::initializer_list ilist) -> iterator { for (pointer p : ilist) { insert( pos, p ); } return iterator{pos.get()}; } template auto intrusive_list::erase(iterator pos) -> iterator { unlink(pos.get()); pos.get()->list_ = nullptr; --size_; return iterator{pos.get()->next_}; } template auto intrusive_list::erase(iterator first, iterator last) -> iterator { while (first != last) { first = erase(first); } return last; } template inline void intrusive_list::push_back(pointer value) { insert(cend(), value); } template void intrusive_list::pop_back() { intrusive_node *old = end_.prev_; end_.prev_ = old->prev_; unlink(old); --size_; } template inline void intrusive_list::push_front(pointer value) { insert(begin(), value); } template inline void intrusive_list::pop_front() { erase(begin()); } template void intrusive_list::remove( pointer value ) { node_type* n = &(value->*node_); if (n->list_ == this) { unlink(n); --size_; } } template template< class UnaryPredicate > void intrusive_list::remove_if( UnaryPredicate pred ) { auto it = begin(); while (it != end()) { pointer p = it.get()->ptr_; ++it; if (pred(p)) { remove(p); } } } template inline void intrusive_list::link(node_type* lhs, node_type* rhs) { if ( lhs ) { lhs->next_ = rhs; } rhs->prev_ = lhs; } template inline void intrusive_list::unlink(node_type* node) { if (node->next_) { node->next_->prev_ = node->prev_; } if (node->prev_) { node->prev_->next_ = node->next_; } }