8#ifndef STLAB_FOREST_HPP
9#define STLAB_FOREST_HPP
38#include <stlab/config.hpp>
44STLAB_VERSION_NAMESPACE_BEGIN()
62constexpr auto forest_trailing_edge{forest_edge::trailing};
63constexpr auto forest_leading_edge{forest_edge::leading};
73 i.edge() =
pivot(i.edge());
88 i.edge() = forest_edge::leading;
95 i.edge() = forest_edge::trailing;
133 }
while (i.edge() != forest_edge::trailing);
140auto has_children(
const I& i) ->
bool {
141 return !i.equal_node(std::next(
leading_of(i)));
149struct child_iterator {
150 using value_type =
typename std::iterator_traits<I>::value_type;
151 using difference_type =
typename std::iterator_traits<I>::difference_type;
152 using reference =
typename std::iterator_traits<I>::reference;
153 using pointer =
typename std::iterator_traits<I>::pointer;
154 using iterator_category =
typename std::iterator_traits<I>::iterator_category;
156 child_iterator() =
default;
157 explicit child_iterator(
const I& x) : _x(std::move(x)) {}
159 child_iterator(
const child_iterator<U>& u) : _x(u.base()) {}
161 [[nodiscard]]
auto base()
const -> I {
return _x; }
163 auto operator*() -> reference {
return dereference(); }
164 auto operator->() -> pointer {
return &dereference(); }
165 auto operator++() ->
auto& {
169 auto operator++(
int) -> child_iterator {
174 auto operator--() ->
auto& {
178 auto operator--(
int) -> child_iterator {
184 friend auto operator==(
const child_iterator& a,
const child_iterator& b) ->
bool {
185 return a.base() == b.base();
187 friend auto operator!=(
const child_iterator& a,
const child_iterator& b) ->
bool {
203 auto dereference() -> reference {
return *_x; }
211 while (x.edge() != edge)
219 while (x.edge() != edge)
228template <
class I, forest_edge Edge>
229struct edge_iterator {
230 using value_type =
typename std::iterator_traits<I>::value_type;
231 using difference_type =
typename std::iterator_traits<I>::difference_type;
232 using reference =
typename std::iterator_traits<I>::reference;
233 using pointer =
typename std::iterator_traits<I>::pointer;
234 using iterator_category =
typename std::iterator_traits<I>::iterator_category;
236 edge_iterator() =
default;
237 explicit edge_iterator(
const I& x) : _x(
find_edge(x, Edge)) {}
239 edge_iterator(
const edge_iterator<U, Edge>& u) : _x(u.base()) {}
241 [[nodiscard]]
auto base()
const -> I {
return _x; }
243 auto operator*() -> reference {
return dereference(); }
244 auto operator->() -> pointer {
return &dereference(); }
245 auto operator++() ->
auto& {
249 auto operator++(
int) -> edge_iterator {
254 auto operator--() ->
auto& {
258 auto operator--(
int) -> edge_iterator {
264 friend auto operator==(
const edge_iterator& a,
const edge_iterator& b) ->
bool {
265 return a.base() == b.base();
267 friend auto operator!=(
const edge_iterator& a,
const edge_iterator& b) ->
bool {
274 void increment() { _x =
find_edge(std::next(_x), Edge); }
278 auto dereference() -> reference {
return *_x; }
287struct filter_fullorder_iterator {
288 using value_type =
typename std::iterator_traits<I>::value_type;
289 using difference_type =
typename std::iterator_traits<I>::difference_type;
290 using reference =
typename std::iterator_traits<I>::reference;
291 using pointer =
typename std::iterator_traits<I>::pointer;
292 using iterator_category =
typename std::iterator_traits<I>::iterator_category;
294 filter_fullorder_iterator() =
default;
296 filter_fullorder_iterator(I f, I l, P p) :
297 _x(skip_forward(f, l, p)), _inside(
true), _first(f), _last(l), _predicate(p) {}
299 filter_fullorder_iterator(I f, I l) :
300 _x(skip_forward(f, l, P())), _inside(
true), _first(f), _last(l) {}
303 filter_fullorder_iterator(
const filter_fullorder_iterator<U, P>& x) :
304 _x(x.base()), _inside(x._inside), _first(x._first), _last(x._last),
305 _predicate(x._predicate) {}
307 auto predicate()
const -> P {
return _predicate; }
309 [[nodiscard]]
auto edge()
const ->
forest_edge {
return this->base().edge(); }
310 auto edge() ->
forest_edge& {
return this->base_reference().edge(); }
312 auto equal_node(
const filter_fullorder_iterator& y)
const ->
bool {
313 return this->base().equal_node(y.base());
316 auto base()
const -> I {
return _x; }
317 auto base_reference() -> I& {
return _x; }
319 auto operator*() -> reference {
return dereference(); }
320 auto operator->() -> pointer {
return &dereference(); }
321 auto operator++() ->
auto& {
325 auto operator++(
int) -> filter_fullorder_iterator {
330 auto operator--() ->
auto& {
334 auto operator--(
int) -> filter_fullorder_iterator {
340 friend auto operator==(
const filter_fullorder_iterator& a,
const filter_fullorder_iterator& b)
342 return a.base() == b.base();
344 friend auto operator!=(
const filter_fullorder_iterator& a,
const filter_fullorder_iterator& b)
359 if (i == _last) _inside =
false;
361 if (i == _first) _inside =
true;
362 if (_inside) i = skip_forward(i, _last, _predicate);
363 this->base_reference() = i;
366 static auto skip_forward(I f, I l, P p) -> I
369 while ((f.edge() == forest_edge::leading) && (f != l) && !p(*f)) {
370 f.edge() = forest_edge::trailing;
376 static auto skip_backward(I f, I l, P p) -> I
379 while ((l.edge() == forest_edge::trailing) && (f != l) && !p(*l)) {
380 l.edge() = forest_edge::leading;
389 if (i == _first) _inside =
false;
391 if (i == _last) _inside =
true;
392 if (_inside) i = skip_backward(_first, i, _predicate);
393 this->base_reference() = i;
396 auto dereference() -> reference {
return *_x; }
403struct reverse_fullorder_iterator {
404 using iterator_type = I;
406 using value_type =
typename std::iterator_traits<I>::value_type;
407 using difference_type =
typename std::iterator_traits<I>::difference_type;
408 using reference =
typename std::iterator_traits<I>::reference;
409 using pointer =
typename std::iterator_traits<I>::pointer;
410 using iterator_category =
typename std::iterator_traits<I>::iterator_category;
412 reverse_fullorder_iterator() : _edge(forest_edge::trailing) {}
413 explicit reverse_fullorder_iterator(I x) : _base(--x), _edge(
pivot(_base.edge())) {}
415 reverse_fullorder_iterator(
const reverse_fullorder_iterator<U>& x) :
416 _base(--x.base()), _edge(
pivot(_base.edge())) {}
418 [[nodiscard]]
auto base()
const -> iterator_type {
return std::next(_base); }
420 [[nodiscard]]
auto edge()
const ->
forest_edge {
return _edge; }
423 [[nodiscard]]
auto equal_node(
const reverse_fullorder_iterator& y)
const ->
bool {
424 return _base.equal_node(y._base);
427 auto operator*() -> reference {
return dereference(); }
428 auto operator->() -> pointer {
return &dereference(); }
429 auto operator++() ->
auto& {
433 auto operator++(
int) -> reverse_fullorder_iterator {
438 auto operator--() ->
auto& {
442 auto operator--(
int) -> reverse_fullorder_iterator {
448 friend auto operator==(
const reverse_fullorder_iterator& a,
const reverse_fullorder_iterator& b)
452 friend auto operator!=(
const reverse_fullorder_iterator& a,
const reverse_fullorder_iterator& b)
462 _base.edge() =
pivot(_edge);
464 _edge =
pivot(_base.edge());
467 _base.edge() =
pivot(_edge);
469 _edge =
pivot(_base.edge());
471 [[nodiscard]]
auto dereference()
const -> reference {
return *_base; }
473 [[nodiscard]]
auto equal(
const reverse_fullorder_iterator& y)
const ->
bool {
474 return (_base == y._base) && (_edge == y._edge);
482struct depth_fullorder_iterator {
483 using value_type =
typename std::iterator_traits<I>::value_type;
484 using difference_type =
typename std::iterator_traits<I>::difference_type;
485 using reference =
typename std::iterator_traits<I>::reference;
486 using pointer =
typename std::iterator_traits<I>::pointer;
487 using iterator_category =
typename std::iterator_traits<I>::iterator_category;
489 depth_fullorder_iterator(difference_type d = 0) : _depth(d) {}
490 explicit depth_fullorder_iterator(I x, difference_type d = 0) : _x(x), _depth(d) {}
492 depth_fullorder_iterator(
const depth_fullorder_iterator<U>& x) :
493 _x(x.base()), _depth(x._depth) {}
495 auto depth()
const -> difference_type {
return _depth; }
496 [[nodiscard]]
auto edge()
const ->
forest_edge {
return this->base().edge(); }
498 auto equal_node(depth_fullorder_iterator
const& y)
const ->
bool {
499 return this->base().equal_node(y.base());
502 auto base()
const -> I {
return _x; }
504 auto operator*() -> reference {
return dereference(); }
505 auto operator->() -> pointer {
return &dereference(); }
506 auto operator++() ->
auto& {
510 auto operator++(
int) -> depth_fullorder_iterator {
515 auto operator--() ->
auto& {
519 auto operator--(
int) -> depth_fullorder_iterator {
525 friend auto operator==(
const depth_fullorder_iterator& a,
const depth_fullorder_iterator& b)
527 return a.base() == b.base();
529 friend auto operator!=(
const depth_fullorder_iterator& a,
const depth_fullorder_iterator& b)
536 difference_type _depth;
541 if (old_edge == edge())
542 _depth += difference_type(
static_cast<std::size_t
>(old_edge) << 1) - 1;
548 if (old_edge == edge())
549 _depth -= difference_type(
static_cast<std::size_t
>(old_edge) << 1) - 1;
552 auto dereference() -> reference {
return *_x; }
557template <
class Forest>
570 enum next_prior_t : std::uint8_t { prior_s, next_s };
573 using reference = node_ptr&;
575 auto link(
forest_edge edge, next_prior_t link) -> node_ptr& {
576 return _nodes[
static_cast<std::size_t
>(edge)][
static_cast<std::size_t
>(link)];
579 [[nodiscard]]
auto link(
forest_edge edge, next_prior_t link)
const -> node_ptr {
580 return _nodes[
static_cast<std::size_t
>(edge)][
static_cast<std::size_t
>(link)];
583 std::array<std::array<node_ptr, 2>, 2> _nodes{
nullptr};
586 _nodes{std::array{static_cast<node_ptr>(this), static_cast<node_ptr>(this)},
587 std::array{static_cast<node_ptr>(this), static_cast<node_ptr>(this)}} {}
591struct node :
public node_base<node<T>> {
592 using value_type = T;
594 explicit node(value_type data) : _data(std::
move(data)) {}
602struct forest_const_iterator;
605struct forest_iterator {
606 using value_type = T;
607 using difference_type = std::ptrdiff_t;
608 using reference = T&;
610 using iterator_category = std::bidirectional_iterator_tag;
612 forest_iterator() =
default;
614 forest_iterator(
const forest_iterator& x) : _node(x._node), _edge(x._edge) {}
616 auto operator=(
const forest_iterator&) -> forest_iterator& =
default;
618 [[nodiscard]]
auto edge() const ->
forest_edge {
return _edge; }
621 [[nodiscard]]
auto equal_node(forest_iterator
const& y)
const ->
bool {
622 return _node == y._node;
625 auto operator*() const -> reference {
return dereference(); }
626 auto operator->() const -> pointer {
return &dereference(); }
627 auto operator++() ->
auto& {
631 auto operator++(
int) -> forest_iterator {
636 auto operator--() ->
auto& {
640 auto operator--(
int) -> forest_iterator {
646 friend auto operator==(
const forest_iterator& a,
const forest_iterator& b) ->
bool {
649 friend auto operator!=(
const forest_iterator& a,
const forest_iterator& b) ->
bool {
654 friend class stlab::forest<value_type>;
656 friend struct forest_iterator;
658 friend struct forest_const_iterator;
659 friend struct unsafe::set_next_fn<forest_iterator>;
661 using node_t = node<T>;
663 [[nodiscard]]
auto dereference() const -> reference {
return _node->_data; }
666 node_t* next(_node->link(_edge, node_t::next_s));
671 _edge =
forest_edge(next->link(forest_edge::leading, node_t::prior_s) == _node);
677 node_t* next(_node->link(_edge, node_t::prior_s));
680 _edge =
forest_edge(next->link(forest_edge::trailing, node_t::next_s) != _node);
687 [[nodiscard]]
auto equal(
const forest_iterator& y)
const ->
bool {
688 return (_node == y._node) && (_edge == y._edge);
691 node_t* _node{
nullptr};
694 forest_iterator(node_t* node,
forest_edge edge) : _node(node), _edge(edge) {}
700struct forest_const_iterator {
701 using value_type =
const T;
702 using difference_type = std::ptrdiff_t;
703 using reference =
const T&;
704 using pointer =
const T*;
705 using iterator_category = std::bidirectional_iterator_tag;
707 forest_const_iterator() =
default;
709 forest_const_iterator(
const forest_const_iterator& x) : _node(x._node), _edge(x._edge) {}
711 auto operator=(
const forest_const_iterator&) -> forest_const_iterator& =
default;
713 forest_const_iterator(
const forest_iterator<T>& x) : _node(x._node), _edge(x._edge) {}
715 [[nodiscard]]
auto edge() const ->
forest_edge {
return _edge; }
717 [[nodiscard]]
auto equal_node(forest_const_iterator
const& y)
const ->
bool {
718 return _node == y._node;
721 auto operator*() const -> reference {
return dereference(); }
722 auto operator->() const -> pointer {
return &dereference(); }
723 auto operator++() ->
auto& {
727 auto operator++(
int) -> forest_const_iterator {
732 auto operator--() ->
auto& {
736 auto operator--(
int) -> forest_const_iterator {
742 friend auto operator==(
const forest_const_iterator& a,
const forest_const_iterator& b) ->
bool {
745 friend auto operator!=(
const forest_const_iterator& a,
const forest_const_iterator& b) ->
bool {
751 friend class stlab::forest;
753 friend struct forest_const_iterator;
754 friend struct unsafe::set_next_fn<forest_const_iterator>;
756 using node_t =
const node<T>;
758 [[nodiscard]]
auto dereference() const -> reference {
return _node->_data; }
761 node_t* next(_node->link(_edge, node_t::next_s));
766 _edge =
forest_edge(next->link(forest_edge::leading, node_t::prior_s) == _node);
772 node_t* next(_node->link(_edge, node_t::prior_s));
775 _edge =
forest_edge(next->link(forest_edge::trailing, node_t::next_s) != _node);
782 [[nodiscard]]
auto equal(
const forest_const_iterator& y)
const ->
bool {
783 return (_node == y._node) && (_edge == y._edge);
786 node_t* _node{
nullptr};
789 forest_const_iterator(node_t* node,
forest_edge edge) : _node(node), _edge(edge) {}
804 void operator()(detail::forest_iterator<T> x, detail::forest_iterator<T> y)
const {
805 using node_t =
typename detail::node<T>;
807 x._node->link(x.edge(), node_t::next_s) = y._node;
808 y._node->link(y.edge(), node_t::prior_s) = x._node;
837 using node_t = detail::node<T>;
842 using reference = T&;
843 using const_reference =
const T&;
844 using iterator = detail::forest_iterator<T>;
845 using const_iterator = detail::forest_const_iterator<T>;
846 using size_type = std::size_t;
847 using difference_type = std::ptrdiff_t;
848 using value_type = T;
850 using const_pointer =
const T*;
859 using reverse_child_iterator = std::reverse_iterator<child_iterator>;
867 ~forest() { clear(); }
869 forest(
const forest& x) {
870 insert(end(), const_child_iterator(x.begin()), const_child_iterator(x.end()));
872 forest(forest&& x) noexcept : forest() { splice(end(), x); }
873 auto operator=(
const forest& x) -> forest& {
875 assert(
this != &x &&
"self-assignment is not allowed");
876 return *
this = forest(x);
879 auto operator=(forest&& x)
noexcept -> forest& {
880 auto tmp{std::move(x)};
886 void swap(forest& x)
noexcept { std::swap(*
this, x); }
896 auto size()
const -> size_type;
897 auto max_size()
const -> size_type {
return size_type(-1); }
898 auto size_valid()
const ->
bool {
return _size != 0 || empty(); }
899 auto empty()
const ->
bool {
900 return begin() == end();
904 auto root() -> iterator {
return iterator(tail(), forest_edge::leading); }
905 auto root()
const -> const_iterator {
return const_iterator(tail(), forest_edge::leading); }
907 auto begin() -> iterator {
return ++root(); }
908 auto end() -> iterator {
return iterator(tail(), forest_edge::trailing); }
909 auto begin()
const -> const_iterator {
return ++root(); }
910 auto end()
const -> const_iterator {
return const_iterator(tail(), forest_edge::trailing); }
912 auto rbegin() -> reverse_iterator {
return reverse_iterator(end()); }
913 auto rend() -> reverse_iterator {
return reverse_iterator(begin()); }
914 auto rbegin()
const -> const_reverse_iterator {
return const_reverse_iterator(end()); }
915 auto rend()
const -> const_reverse_iterator {
return const_reverse_iterator(begin()); }
917 auto front() -> reference {
921 auto front()
const -> const_reference {
925 auto back() -> reference {
929 auto back()
const -> const_reference {
936 erase(begin(), end());
945 auto erase(
const iterator& position) -> iterator;
951 auto erase(
const iterator& first,
const iterator& last) -> iterator;
953 auto insert(
const iterator& position, T x) -> iterator {
954 iterator result(
new node_t(std::move(x)), forest_edge::leading);
956 if (size_valid()) ++_size;
964 void push_front(
const T& x) { insert(begin(), x); }
965 void push_back(
const T& x) { insert(end(), x); }
975 auto insert(iterator position,
976 const const_child_iterator& first,
977 const const_child_iterator& last) -> iterator;
979 auto splice(
const iterator& position, forest<T>& x) -> iterator;
980 auto splice(
const iterator& position, forest<T>& x, iterator i) -> iterator;
981 auto splice(
const iterator& position, forest<T>& x, child_iterator first, child_iterator last)
983 auto splice(
const iterator& position,
985 const child_iterator& first,
986 const child_iterator& last,
987 size_type count) -> iterator;
989 auto insert_parent(child_iterator front, child_iterator back,
const T& x) -> iterator;
990 void reverse(child_iterator first, child_iterator last);
993 friend struct detail::forest_iterator<value_type>;
994 friend struct detail::forest_const_iterator<value_type>;
997 mutable std::atomic<size_type> _size{0};
998 detail::node_base<node_t> _tail;
1000 auto tail() -> node_t* {
return static_cast<node_t*
>(&_tail); }
1001 auto tail()
const ->
const node_t* {
return static_cast<const node_t*
>(&_tail); }
1008 if (x.size() != y.size())
return false;
1010 for (
auto first(x.begin()), last(x.end()), pos(y.begin()); first != last; ++first, ++pos) {
1011 if (first.edge() != pos.edge())
return false;
1012 if (
is_leading(first) && (*first != *pos))
return false;
1044 if (!size_valid()) {
1045 const_preorder_iterator first(begin());
1046 const_preorder_iterator last(end());
1048 _size = size_type(std::distance(first, last));
1058 difference_type stack_depth(0);
1059 iterator position(first);
1061 while (position != last) {
1062 if (position.edge() == forest_edge::leading) {
1066 if (stack_depth > 0)
1067 position =
erase(position);
1070 stack_depth = std::max<difference_type>(0, stack_depth - 1);
1086 if (size_valid()) --_size;
1088 iterator leading_prior(std::prev(
leading_of(position)));
1089 iterator leading_next(std::next(
leading_of(position)));
1090 iterator trailing_prior(std::prev(
trailing_of(position)));
1091 iterator trailing_next(std::next(
trailing_of(position)));
1093 if (has_children(position)) {
1100 delete position._node;
1102 return is_leading(position) ? std::next(leading_prior) : trailing_next;
1108auto forest<T>::splice(
const iterator& position,
forest<T>& x) -> iterator {
1110 x.size_valid() ? x.size() : 0);
1116auto forest<T>::splice(
const iterator& position, forest<T>& x, iterator i) -> iterator {
1117 i.edge() = forest_edge::leading;
1118 return splice(position, x, child_iterator(i), ++child_iterator(i), has_children(i) ? 0 : 1);
1124auto forest<T>::insert(iterator pos,
const const_child_iterator& f,
const const_child_iterator& l)
1126 for (const_iterator first(f.base()), last(l.base()); first != last; ++first, ++pos) {
1127 if (
is_leading(first)) pos = insert(pos, *first);
1136auto forest<T>::splice(
const iterator& position,
1140 size_type count) -> iterator {
1141 if (first == last || first.base() == position)
return position;
1145 if (size_valid()) _size += count;
1146 if (x.size_valid()) x._size -= count;
1153 iterator back(std::prev(last.base()));
1160 return first.base();
1166auto forest<T>::splice(
const iterator& position,
1170 return splice(position, x, first, last, 0);
1177 typename forest<T>::iterator {
1178 iterator result(insert(last.base(), x));
1179 if (first == last)
return result;
1188 iterator prior(first.base());
1214template <
class Forest>
1215class child_adaptor {
1217 using forest_type = Forest;
1218 using value_type =
typename Forest::value_type;
1219 using iterator_type =
typename Forest::iterator;
1220 using reference =
typename Forest::reference;
1221 using const_reference =
typename Forest::const_reference;
1222 using difference_type =
typename Forest::difference_type;
1223 using iterator =
typename Forest::child_iterator;
1225 child_adaptor() =
delete;
1226 child_adaptor(forest_type& f, iterator_type& i) : _forest(f), _iterator(i) {}
1228 auto back() -> value_type& {
return *(--
child_end(_iterator)); }
1229 auto front() -> value_type& {
return *(
child_begin(_iterator)); }
1231 void push_back(
const value_type& x) { _forest.insert(
child_end(_iterator).base(), x); }
1232 void push_front(
const value_type& x) { _forest.insert(
child_begin(_iterator).base(), x); }
1234 void pop_back() { _forest.erase(--
child_end(_iterator).base()); }
1235 void pop_front() { _forest.erase(
child_begin(_iterator).base()); }
1238 forest_type& _forest;
1239 iterator_type& _iterator;
1250 [[nodiscard]]
auto begin()
const {
return _f; }
1251 [[nodiscard]]
auto end()
const {
return _l; }
1265template <
class R,
typename P>
1270 iterator(std::end(x), std::end(x), p)};
1274template <
class R,
typename P>
1279 iterator(std::end(x), std::end(x), p)};
1339auto preorder_range(R& x) {
1340 using iterator = edge_iterator<typename R::iterator, forest_edge::leading>;
1342 return forest_range<iterator>{iterator(std::begin(x)), iterator(std::end(x))};
1347auto preorder_range(
const R& x) {
1357STLAB_VERSION_NAMESPACE_END()
Presents the children of a node (given by a fullorder iterator into forest) as a small sequence-like ...
Definition forest.hpp:1215
Hierarchical, node-based container: a forest (ordered sequence of trees) with fullorder iterators and...
Definition forest.hpp:835
auto find_edge(I x, forest_edge edge) -> I
Advances x forward until x.edge() == edge (or returns last such position).
Definition forest.hpp:210
constexpr auto is_trailing(forest_edge e)
True if e is a trailing-edge position.
Definition forest.hpp:111
auto find_edge_reverse(I x, forest_edge edge) -> I
Advances x backward until x.edge() == edge.
Definition forest.hpp:218
auto trailing_of(I i)
Positions i on the trailing edge of the same node.
Definition forest.hpp:94
auto postorder_range(R &x)
Postorder (trailing-edge) walk over x.
Definition forest.hpp:1322
constexpr auto pivot(forest_edge e)
Toggles a forest_edge between leading and trailing.
Definition forest.hpp:68
auto depth_range(R &x)
Fullorder walk with depth tracking over x (depth_fullorder_iterator).
Definition forest.hpp:1304
auto find_parent(I i) -> I
Returns the trailing-edge iterator of the parent of the subtree containing i.
Definition forest.hpp:130
auto erase(const iterator &position) -> iterator
Erases the node at position.
Definition forest.hpp:1079
auto child_end(const I &x) -> child_iterator< I >
One-past-last child iterator for the node referenced by x (half-open child sequence).
Definition forest.hpp:1206
auto child_begin(const I &x) -> child_iterator< I >
First child iterator for the node referenced by fullorder iterator x (may equal child_end).
Definition forest.hpp:1198
auto size() const -> size_type
Returns the number of nodes; when size_valid() is true, otherwise a linear walk.
Definition forest.hpp:1043
auto filter_fullorder_range(R &x, P p)
Range of filter_fullorder_iterator over x using predicate p.
Definition forest.hpp:1266
forest_edge
Leading and trailing visits in a fullorder walk of a node (see forest iterators).
Definition forest.hpp:60
auto leading_of(I i)
Positions i on the leading edge of the same node.
Definition forest.hpp:87
auto pivot_of(I i)
Returns a copy of i with its edge toggled (pivot).
Definition forest.hpp:78
auto reverse_fullorder_range(R &x)
Reverses the fullorder traversal of x (see reverse_fullorder_iterator).
Definition forest.hpp:1286
constexpr auto is_leading(forest_edge e)
True if e is a leading-edge position.
Definition forest.hpp:102
auto child_range(const I &x)
forest_range of child_iterator over the immediate children of the node at x.
Definition forest.hpp:1258
void set_next(const I &x, const I &y)
Sets the successor of the node referenced by x to y (via set_next_fn<I>).
Definition set_next.hpp:41
constexpr auto move(T &&t) noexcept -> std::remove_reference_t< T > &&
A standard move implementation but with a compile-time check for const types.
Definition utility.hpp:154
Definition reverse.hpp:39
auto reverse_nodes(I first, I last) -> I
Reverses the range [first, last) and returns the beginning of the reversed range such that [result,...
Definition reverse.hpp:70
Definition reverse.hpp:28
Reverse algorithms for iterators and intrusive forward / bidirectional sequences.
Intrusive forward/bidirectional iterator helpers (set_next, splice, skip).
Iterator over the child sequence of a node: adapts a fullorder iterator to visit only immediate child...
Definition forest.hpp:149
Fullorder iterator that tracks depth in the tree as it advances or retreats.
Definition forest.hpp:482
Fullorder iterator restricted to a single edge kind: visits only leading or trailing positions (e....
Definition forest.hpp:229
Fullorder iterator that visits only positions whose values satisfy predicate P (skipping others by ad...
Definition forest.hpp:287
Half-open range [begin, end) of forest iterators; used by child_range, preorder_range,...
Definition forest.hpp:1246
Reverses the direction of a fullorder walk while preserving edge semantics (bidirectional).
Definition forest.hpp:403
Hook for intrusive iterators: specialize to set the successor of the node at x to y.
Definition set_next.hpp:35