ROSE  0.11.145.0
Tree.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef Sawyer_TreeVertex_H
9 #define Sawyer_TreeVertex_H
10 
11 #include <Sawyer/Assert.h>
12 #include <Sawyer/Exception.h>
13 
14 #include <boost/lexical_cast.hpp>
15 #include <boost/range/adaptor/reversed.hpp>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 namespace Sawyer {
21 
27 namespace Tree {
28 
33 enum class TraversalEvent {
34  ENTER,
35  LEAVE
36 };
37 
113 template<class B>
114 class Vertex: public std::enable_shared_from_this<Vertex<B>> {
115 public:
116 
118  using UserBase = B;
119 
121  using UserBasePtr = std::shared_ptr<UserBase>;
122 
125 
126 public:
127  template<class T> class Edge;
128  template<class T> class EdgeVector;
129 
131  // Errors and exceptions
133 
136  public:
139 
141  Exception(const std::string &mesg, const UserBasePtr &vertex)
142  : Sawyer::Exception::RuntimeError(mesg), vertex(vertex) {}
143 
144  ~Exception() {}
145  };
146 
150  class InsertionError: public Exception {
151  public:
154  : Exception("vertex is already attached to a tree", vertex) {}
155  };
156 
160  class CycleError: public Exception {
161  public:
163  explicit CycleError(const UserBasePtr &vertex)
164  : Exception("insertion of vertex would cause a cycle in the tree", vertex) {}
165  };
166 
168  // Child-to-parent edges
170 
180  class ReverseEdge {
181  private:
182  Vertex &child_; // required child vertex owning this edge
183 
184  // The parent pointer is a raw pointer because it is safe to do so, and because we need to know the pointer before the
185  // parent is fully constructed.
186  //
187  // It is safe (never dangling) because the pointer can only be changed by a forward edge, which is always a member of a
188  // vertex, and the parent pointer is only set to point to that vertex. When the parent is deleted the edge is deleted and
189  // its destructor changes the parent pointer back to null.
190  //
191  // The parent pointer is needed during construction of the parent when the parent has some edge data members that are being
192  // initialized to point to non-null children. This happens during the parent's construction, before the parent has any
193  // shared or weak pointers.
194  UserBase *parent_ = nullptr; // optional parent to which this edge points
195 
196  public:
197  // No default constructor and not copyable.
198  ReverseEdge() = delete;
199  explicit ReverseEdge(const ReverseEdge&) = delete;
200  ReverseEdge& operator=(const ReverseEdge&) = delete;
201 
202  public:
203  ~ReverseEdge(); // internal use only
204  explicit ReverseEdge(Vertex &child); // internal use only
205 
206  public:
210  UserBasePtr operator()() const;
211  UserBasePtr operator->() const;
217  bool operator==(const UserBasePtr&) const;
218  bool operator!=(const UserBasePtr&) const;
219  bool operator==(const ReverseEdge&) const;
220  bool operator!=(const ReverseEdge&) const;
221  template<class T> bool operator==(const Edge<T>&) const;
222  template<class T> bool operator!=(const Edge<T>&) const;
226  explicit operator bool() const {
227  return parent_ != nullptr;
228  }
229 
230  private:
231  // Used internally through ReverseEdgeAccess when a Edge<T> adjusts the ReverseEdge
232  template<class T> friend class Edge;
233  void reset();
234  void set(UserBase &parent);
235  };
236 
238  // Base class for parent-to-child edges
240 private:
241  enum class Link { NO, YES };
242 
243  // Used internally as the non-template abstract base class for all parent-to-child edge types.
244  class EdgeBase {
245  public:
246  // Previous edge in this object, including edges defined in base classes. Edges in this linked list are ordered so that
247  // if edge A was initialized before edge B, then edge A will appear earlier in the list. The "prev" pointers in the list
248  // point backward through the list.
249  EdgeBase *prev;
250 
251  virtual ~EdgeBase() {}
252  EdgeBase() = delete;
253  EdgeBase(const EdgeBase&) = delete;
254  EdgeBase& operator=(const EdgeBase&) = delete;
255  explicit EdgeBase(EdgeBase *prev)
256  : prev(prev) {}
257 
258  // Number of child pointers in this edge. Edges are either 1:1 or 1:N. Some of the child pointers could be null.
259  virtual size_t size() const = 0;
260 
261  // Return the i'th pointer. The argument is expected to be in the domain.
262  virtual Vertex* pointer(size_t i) const = 0;
263 
264  // Traverse through all the non-null children of appropriate type pointed to by all edges in the order that the edges were
265  // initialized. The visitor is invoked with two arguments: a non-null shared pointer to the child, and an indication of
266  // whether this is a pre- or post-order visit. The first visitor call that returns a value that is true in a Boolean context
267  // short circuits the traversal and that value becomes the return value of the traversal.
268  template<class T, class Visitor>
269  auto traverse(Visitor visitor) -> decltype(visitor(std::shared_ptr<T>(), TraversalEvent::ENTER)) {
270  if (prev) {
271  if (auto retval = prev->traverse<T>(visitor))
272  return retval;
273  }
274  for (size_t i = 0; i < size(); ++i) {
275  if (auto child = pointer(i)) {
276  if (auto retval = child->template traverse<T>(visitor))
277  return retval;
278  }
279  }
280  return decltype(visitor(std::shared_ptr<T>(), TraversalEvent::ENTER))();
281  }
282  };
283 
285  // 1:1 parent-to-child edge
287 public:
320  template<class T>
321  class Edge: public EdgeBase {
322  public:
324  using Child = T;
325 
327  using ChildPtr = std::shared_ptr<Child>;
328 
329  private:
330  UserBase &parent_; // required parent owning this child edge
331  ChildPtr child_; // optional child to which this edge points
332 
333  public:
335  ~Edge();
336 
347  explicit Edge(UserBase &parent);
348  Edge(UserBase &parent, const ChildPtr &child);
351  private:
352  template<class U> friend class EdgeVector;
353  // Used internally to initialize an edge without linking it to prior edges
354  Edge(Link, UserBase &parent, const ChildPtr &child);
355 
356  public:
360  const ChildPtr& operator->() const;
361  const ChildPtr& operator()() const;
367  bool operator==(const UserBasePtr&) const;
368  bool operator!=(const UserBasePtr&) const;
369  bool operator==(const ReverseEdge&) const;
370  bool operator!=(const ReverseEdge&) const;
371  template<class U> bool operator==(const Edge<U>&) const;
372  template<class U> bool operator!=(const Edge<U>&) const;
392  if (child != child_) {
393  checkChildInsertion(child);
394 
395  // Unlink the child from the tree
396  if (child_) {
397  child_->parent.reset(); // child-to-parent edge
398  child_.reset(); // parent-to-child edge
399  }
400 
401  // Link new child into the tree
402  if (child) {
403  child->parent.set(parent_);
404  child_ = child;
405  }
406  }
407  return *this;
408  }
409 
411  return (*this) = parent();
412  }
416  explicit operator bool() const {
417  return child_ != nullptr;
418  }
419 
420  private:
421  void checkChildInsertion(const ChildPtr &child) const;
422 
423  size_t size() const override {
424  return 1;
425  }
426 
427  Vertex* pointer(size_t i) const override {
428  ASSERT_always_require(0 == i);
429  return child_.get();
430  }
431  };
432 
434  // 1:N parent-to-child edge
436 public:
440  template<class T>
441  class EdgeVector: public EdgeBase {
442  public:
444  using Child = T;
445 
447  using ChildPtr = std::shared_ptr<Child>;
448 
449  private:
450  using Vector = std::vector<std::unique_ptr<Edge<Child>>>;
451 
452  public:
453  using value_type = Edge<Child>;
454  using size_type = typename Vector::size_type;
455  using difference_type = typename Vector::difference_type;
456  using reference = value_type&;
457  using const_reference = const value_type&;
458 
459  public:
460  template<class BaseIterator>
461  class Iterator {
462  BaseIterator baseIterator_;
463 
464  public:
465  Iterator() = delete;
466  Iterator(const BaseIterator &baseIterator)
467  : baseIterator_(baseIterator) {}
468 
469  Iterator(const Iterator &other)
470  : baseIterator_(other.baseIterator_) {}
471 
472  Iterator& operator=(const Iterator &other) {
473  baseIterator_ = other.baseIterator_;
474  return *this;
475  }
476 
477  Iterator& operator++() {
478  ++baseIterator_;
479  return *this;
480  }
481 
482  Iterator operator++(int) {
483  Iterator temp = *this;
484  ++baseIterator_;
485  return temp;
486  }
487 
488  Iterator& operator--() {
489  --baseIterator_;
490  return *this;
491  }
492 
493  Iterator operator--(int) {
494  Iterator temp = *this;
495  --baseIterator_;
496  return temp;
497  }
498 
499  Iterator& operator+=(difference_type n) {
500  baseIterator_ += n;
501  return *this;
502  }
503 
504  Iterator operator+(difference_type n) const {
505  Iterator retval = *this;
506  retval += n;
507  return retval;
508  }
509 
510  Iterator& operator-=(difference_type n) {
511  baseIterator_ -= n;
512  return *this;
513  }
514 
515  Iterator operator-(difference_type n) const {
516  Iterator retval = *this;
517  retval -= n;
518  return retval;
519  }
520 
521  difference_type operator-(const Iterator &other) const {
522  return other.baseIterator_ - baseIterator_;
523  }
524 
525  auto& operator*() const {
526  ASSERT_not_null(*baseIterator_);
527  return **baseIterator_;
528  }
529 
530  auto& operator->() const {
531  ASSERT_not_null(*baseIterator_);
532  return &**baseIterator_;
533  }
534 
535  auto& operator[](difference_type i) const {
536  ASSERT_not_null(baseIterator_[i]);
537  return *baseIterator_[i];
538  }
539 
540  bool operator==(const Iterator &other) const {
541  return baseIterator_ == other.baseIterator_;
542  }
543 
544  bool operator!=(const Iterator &other) const {
545  return baseIterator_ != other.baseIterator_;
546  }
547 
548  bool operator<(const Iterator &other) const {
549  return baseIterator_ < other.baseIterator_;
550  }
551 
552  bool operator<=(const Iterator &other) const {
553  return baseIterator_ <= other.baseIterator_;
554  }
555 
556  bool operator>(const Iterator &other) const {
557  return baseIterator_ > other.baseIterator_;
558  }
559 
560  bool operator>=(const Iterator &other) const {
561  return baseIterator_ >= other.baseIterator_;
562  }
563  };
564 
565  public:
567 
568  private:
569  UserBase &parent_; // required parent owning this child edge
570  Vector edges_;
571 
572  public:
575 
581  explicit EdgeVector(UserBase &parent);
582 
583  public:
587  bool empty() const {
588  return edges_.empty();
589  }
590 
594  size_t size() const override {
595  return edges_.size();
596  }
597 
599  void reserve(size_t n) {
600  edges_.reserve(n);
601  }
602 
604  size_t capacity() const {
605  return edges_.capacity();
606  }
607 
612  void push_back(const ChildPtr& elmt) {
613  auto edge = std::unique_ptr<Edge<Child>>(new Edge<Child>(Link::NO, parent_, elmt));
614  edges_.push_back(std::move(edge));
615  }
616 
620  void pop_back() {
621  ASSERT_forbid(edges_.empty());
622  edges_.pop_back();
623  }
624 
628  const Edge<Child>& at(size_t i) const {
629  ASSERT_require(i < edges_.size());
630  return *edges_.at(i);
631  }
632  Edge<Child>& at(size_t i) {
633  ASSERT_require(i < edges_.size());
634  return *edges_.at(i);
635  }
636  const Edge<Child>& operator[](size_t i) const {
637  return at(i);
638  }
639  Edge<Child>& operator[](size_t i) {
640  return at(i);
641  }
647  const Edge<Child>& front() const {
648  ASSERT_forbid(empty());
649  return at(0);
650  }
652  ASSERT_forbid(empty());
653  return at(0);
654  }
660  const Edge<Child>& back() const {
661  ASSERT_forbid(empty());
662  return at(size() - 1);
663  }
665  ASSERT_forbid(empty());
666  return at(size() - 1);
667  }
672  return iterator(edges_.begin());
673  }
674 
677  return iterator(edges_.end());
678  }
679 
680  protected:
681  Vertex* pointer(size_t i) const override {
682  return at(i)().get();
683  }
684  };
685 
687  // Vertex
689 public:
694  ReverseEdge parent;
695  EdgeBase *treeEdges_ = nullptr;
696 
697 protected:
698  virtual void destructorHelper() {}
699  Vertex();
700 
701 public:
704 
708  template<class T>
709  std::shared_ptr<T> isa();
710 
742  template<class T, class Visitor>
743  auto traverseReverse(const Visitor &visitor) {
744  auto vertex = std::dynamic_pointer_cast<T>(this->pointer());
745  if (vertex) {
746  if (auto result = visitor(vertex, TraversalEvent::ENTER))
747  return result;
748  }
749 
750  if (parent) {
751  if (auto result = parent()->template traverseReverse<T>(visitor))
752  return result;
753  }
754 
755  if (vertex) {
756  return visitor(vertex, TraversalEvent::LEAVE);
757  } else {
758  return decltype(visitor(vertex, TraversalEvent::ENTER))();
759  }
760  }
761 
770  template<class T, class Visitor>
771  auto traverse(const Visitor &visitor) {
772  auto vertex = std::dynamic_pointer_cast<T>(this->pointer());
773  if (vertex) {
774  if (auto retval = visitor(vertex, TraversalEvent::ENTER))
775  return retval;
776  }
777  if (treeEdges_) {
778  if (auto retval = treeEdges_->template traverse<T>(visitor))
779  return retval;
780  }
781  if (vertex) {
782  return visitor(vertex, TraversalEvent::LEAVE);
783  } else {
784  return decltype(visitor(vertex, TraversalEvent::ENTER))();
785  }
786  }
787 
795  template<class T, class Visitor>
796  auto traversePre(const Visitor &visitor) {
797  return traverse<T>([&visitor] (const std::shared_ptr<T> &vertex, TraversalEvent event) {
798  if (TraversalEvent::ENTER == event) {
799  return visitor(vertex);
800  } else {
801  return decltype(visitor(vertex))();
802  }
803  });
804  }
805 
813  template<class T, class Visitor>
814  auto traversePost(const Visitor &visitor) {
815  return traverse<T>([&visitor] (const std::shared_ptr<T> &vertex, TraversalEvent event) {
816  if (TraversalEvent::LEAVE == event) {
817  return visitor(vertex);
818  } else {
819  return decltype(visitor(vertex))();
820  }
821  });
822  }
823 
825  template<class T>
826  std::shared_ptr<T> findFirstAncestor() {
827  return traverseReverse<T>([](const std::shared_ptr<T> &vertex, TraversalEvent event) {
828  return TraversalEvent::ENTER == event ? vertex : nullptr;
829  });
830  };
831 
833  template<class T>
834  std::shared_ptr<T> findLastAncestor() {
835  return traverseReverse<T>([](const std::shared_ptr<T> &vertex, TraversalEvent event) {
836  return TraversalEvent::LEAVE == event ? vertex : nullptr;
837  });
838  };
839 
844  template<class T>
845  std::vector<std::shared_ptr<T>> findDescendants() {
846  std::vector<std::shared_ptr<T>> retval;
847  traverse<T>([&retval](const std::shared_ptr<T> &vertex, TraversalEvent event) {
848  if (TraversalEvent::ENTER == event)
849  retval.push_back(vertex);
850  });
851  return retval;
852  }
853 
858  UserBasePtr child(size_t i) const;
859 
863  size_t nChildren() const;
864 };
865 
867 // Implementations for ReverseEdge
869 
870 template<class B>
872  ASSERT_require(this->parent_ == nullptr);
873 }
874 
875 template<class B>
877  : child_(child) {}
878 
879 template<class B>
880 typename Vertex<B>::UserBasePtr
882  if (parent_) {
883  return parent_->pointer();
884  } else {
885  return {};
886  }
887 }
888 
889 template<class B>
890 typename Vertex<B>::UserBasePtr
892  ASSERT_not_null(parent_);
893  return parent_->pointer();
894 }
895 
896 template<class B>
897 bool
899  return ptr.get() == parent_;
900 }
901 
902 template<class B>
903 bool
905  return ptr.get() != parent_;
906 }
907 
908 template<class B>
909 bool
911  return parent_ == other.parent_;
912 }
913 
914 template<class B>
915 bool
917  return parent_ != other.parent_;
918 }
919 
920 template<class B>
921 template<class T>
922 bool
924  return parent_ == other();
925 }
926 
927 template<class B>
928 template<class T>
929 bool
931  return parent_ != other();
932 }
933 
934 template<class B>
935 void
937  parent_ = nullptr;
938 }
939 
940 template<class B>
941 void
942 Vertex<B>::ReverseEdge::set(UserBase &parent) {
943  parent_ = &parent;
944 }
945 
947 // Implementations for Edge<T>
949 
950 template<class B>
951 template<class T>
953  if (child_)
954  child_->parent.reset();
955 }
956 
957 template<class B>
958 template<class T>
960  : EdgeBase(parent.treeEdges_), parent_(parent) {
961  parent_.treeEdges_ = this;
962 }
963 
964 template<class B>
965 template<class T>
966 Vertex<B>::Edge<T>::Edge(UserBase &parent, const std::shared_ptr<T> &child)
967  : EdgeBase(parent.treeEdges_), parent_(parent), child_(child) {
968  checkChildInsertion(child);
969  parent_.treeEdges_ = this; // must be after checkChildInsertin for exception safety
970  if (child)
971  child->parent.set(parent);
972 }
973 
974 template<class B>
975 template<class T>
976 Vertex<B>::Edge<T>::Edge(Link link, UserBase &parent, const std::shared_ptr<T> &child)
977  : EdgeBase(Link::YES == link ? parent.treeEdges_ : nullptr), parent_(parent), child_(child) {
978  checkChildInsertion(child);
979  if (Link::YES == link)
980  parent_.treeEdges_ = this; // must be after checkChildInsertin for exception safety
981  if (child)
982  child->parent.set(parent);
983 }
984 
985 template<class B>
986 template<class T>
987 void
988 Vertex<B>::Edge<T>::checkChildInsertion(const std::shared_ptr<T> &child) const {
989  if (child) {
990  if (child->parent)
991  throw InsertionError(child);
992 #ifndef NDEBUG
993  for (const UserBase *p = &parent_; p; p = p->parent().get()) {
994  if (p == child.get())
995  throw CycleError(child);
996  }
997 #endif
998  }
999 }
1000 
1001 template<class B>
1002 template<class T>
1003 const std::shared_ptr<T>&
1005  ASSERT_not_null(child_);
1006  return child_;
1007 }
1008 
1009 template<class B>
1010 template<class T>
1011 const std::shared_ptr<T>&
1013  return child_;
1014 }
1015 
1016 template<class B>
1017 template<class T>
1018 bool
1020  return child_ == ptr;
1021 }
1022 
1023 template<class B>
1024 template<class T>
1025 bool
1027  return child_ != ptr;
1028 }
1029 
1030 template<class B>
1031 template<class T>
1032 bool
1034  return child_ == other();
1035 }
1036 
1037 template<class B>
1038 template<class T>
1039 bool
1041  return child_.get() != other();
1042 }
1043 
1044 template<class B>
1045 template<class T>
1046 template<class U>
1047 bool
1049  return child_.get() == other.get();
1050 }
1051 
1052 template<class B>
1053 template<class T>
1054 template<class U>
1055 bool
1057  return child_.get() != other.get();
1058 }
1059 
1061 // Implementations for EdgeVector<T>
1063 
1064 template<class B>
1065 template<class T>
1067  : EdgeBase(parent.treeEdges_), parent_(parent) {
1068  parent_.treeEdges_ = this;
1069 }
1070 
1072 // Implementations for Vertex<B>
1074 
1075 template<class B>
1077  : parent(*this) {}
1078 
1079 template<class B>
1080 typename Vertex<B>::UserBasePtr
1082  auto retval = std::dynamic_pointer_cast<UserBase>(this->shared_from_this());
1083  ASSERT_not_null(retval);
1084  return retval;
1085 }
1086 
1087 template<class B>
1088 template<class T>
1089 std::shared_ptr<T>
1091  return std::dynamic_pointer_cast<T>(this->shared_from_this());
1092 }
1093 
1094 template<class B>
1095 typename Vertex<B>::UserBasePtr
1096 Vertex<B>::child(size_t i) const {
1097  std::vector<EdgeBase*> edges;
1098  for (const EdgeBase *edge = treeEdges_; edge; edge = edge->prev)
1099  edges.push_back(edge);
1100  for (const EdgeBase *edge: boost::adaptors::reverse(edges)) {
1101  if (i < edge->size()) {
1102  return edge->pointer(i);
1103  } else {
1104  i -= edge->size();
1105  }
1106  }
1107  return {};
1108 }
1109 
1110 template<class B>
1111 size_t
1113  size_t n = 0;
1114  for (const EdgeBase *edge = treeEdges_; edge; edge = edge->prev)
1115  n += edge->size();
1116  return n;
1117 }
1118 
1119 } // namespace
1120 } // namespace
1121 #endif
size_t nChildren() const
Returns the number of children.
Definition: Tree.h:1112
void push_back(const ChildPtr &elmt)
Insert a child pointer at the end of this vertex.
Definition: Tree.h:612
auto traverseReverse(const Visitor &visitor)
Traverse in reverse direction from children to parents.
Definition: Tree.h:743
Exception(const std::string &mesg, const UserBasePtr &vertex)
Construct a new error with the specified message and the causing vertex.
Definition: Tree.h:141
iterator end()
Return an iterator to one past the last edge.
Definition: Tree.h:676
std::shared_ptr< Child > ChildPtr
Type of pointers to children.
Definition: Tree.h:447
std::shared_ptr< Child > ChildPtr
Type of pointer to the child.
Definition: Tree.h:327
RuntimeError(const std::string &mesg)
Constructor taking a description of the error.
bool empty() const
Test whether vector is empty.
Definition: Tree.h:587
iterator begin()
Return an iterator to the first edge.
Definition: Tree.h:671
size_t capacity() const
Reserved capacity.
Definition: Tree.h:604
bool operator!=(const UserBasePtr &) const
Compare the child pointer to another pointer.
Definition: Tree.h:1026
const ChildPtr & operator()() const
Return the child if there is one, else null.
Definition: Tree.h:1012
Edge< Child > & back()
Return the last edge.
Definition: Tree.h:664
EdgeVector(UserBase &parent)
Construct a child edge that belongs to the specified parent.
Definition: Tree.h:1066
A parent-to-child edge in a tree.
Definition: Tree.h:127
void pop_back()
Erase a child edge from the end of this vertex.
Definition: Tree.h:620
std::shared_ptr< T > findLastAncestor()
Traversal that finds the farthest ancestor of type T or derived from T.
Definition: Tree.h:834
Edge< Child > & operator[](size_t i)
Return the i'th edge.
Definition: Tree.h:639
const Edge< Child > & front() const
Return the first edge.
Definition: Tree.h:647
InsertionError(const UserBasePtr &vertex)
Construct a new error with the vertex that caused the error.
Definition: Tree.h:153
Edge & operator=(const ChildPtr &child)
Assign a pointer to a child.
Definition: Tree.h:391
const Edge< Child > & operator[](size_t i) const
Return the i'th edge.
Definition: Tree.h:636
Base class for Sawyer runtime errors.
CycleError(const UserBasePtr &vertex)
Construct a new error with the vertex that caused the error.
Definition: Tree.h:163
UserBasePtr vertex
Vertex that caused the error.
Definition: Tree.h:138
Name space for the entire library.
Definition: FeasiblePath.h:767
Error when attaching a vertex to a tree and the vertex is already attached somewhere else...
Definition: Tree.h:150
Edge(UserBase &parent)
Construct a child edge that belongs to the specified parent.
Definition: Tree.h:959
const Edge< Child > & at(size_t i) const
Return the i'th edge.
Definition: Tree.h:628
Edge< Child > & at(size_t i)
Return the i'th edge.
Definition: Tree.h:632
std::shared_ptr< UserBase > UserBasePtr
Pointer to user's base class.
Definition: Tree.h:121
~EdgeVector()
Destructor clears children's parents.
Definition: Tree.h:574
Edge< Child > & front()
Return the first edge.
Definition: Tree.h:651
ReverseEdge parent
Pointer to the parent in the tree.
Definition: Tree.h:694
std::shared_ptr< T > isa()
Tests whether this object is a certain type.
Definition: Tree.h:1090
~Edge()
Destructor clears child's parent.
Definition: Tree.h:952
Edge & operator=(const ReverseEdge &parent)
Assign a pointer to a child.
Definition: Tree.h:410
void reserve(size_t n)
Reserve space so the child edge vector can grow without being reallocated.
Definition: Tree.h:599
UserBasePtr child(size_t i) const
Returns the pointer for a child.
Definition: Tree.h:1096
TraversalEvent
Traversal event.
Definition: Tree.h:33
Node UserBase
User's base class.
Definition: Tree.h:118
Base class for tree vertices.
Definition: Tree.h:114
Base class for errors and exceptions for this vertex type.
Definition: Tree.h:135
Error when attaching a vertex to a tree would cause a cycle.
Definition: Tree.h:160
bool operator==(const UserBasePtr &) const
Compare the child pointer to another pointer.
Definition: Tree.h:1019
auto traversePre(const Visitor &visitor)
Pre-order forward traversal.
Definition: Tree.h:796
auto traverse(const Visitor &visitor)
Traverse in forward direction from parents to children.
Definition: Tree.h:771
bool operator!=(const UserBasePtr &) const
Compare the parent pointer to another pointer.
Definition: Tree.h:904
bool operator==(const UserBasePtr &) const
Compare the parent pointer to another pointer.
Definition: Tree.h:898
UserBasePtr operator->() const
Return the parent if there is one, else null.
Definition: Tree.h:891
const Edge< Child > & back() const
Return the last edge.
Definition: Tree.h:660
size_t size() const override
Number of child edges.
Definition: Tree.h:594
A 1:N tree edge from parent to children.
Definition: Tree.h:128
const ChildPtr & operator->() const
Return the child if there is one, else null.
Definition: Tree.h:1004
T Child
Type of children being pointed to.
Definition: Tree.h:444
std::shared_ptr< T > findFirstAncestor()
Traversal that finds the closest ancestor of type T or derived from T.
Definition: Tree.h:826
T Child
Type of child being pointed to.
Definition: Tree.h:324
UserBasePtr operator()() const
Return the parent if there is one, else null.
Definition: Tree.h:881
std::vector< std::shared_ptr< T > > findDescendants()
Traversal that finds all the descendants of a particular type.
Definition: Tree.h:845
auto traversePost(const Visitor &visitor)
Post-order forward traversal.
Definition: Tree.h:814
Points from a child to a parent in the tree.
Definition: Tree.h:180
UserBasePtr pointer()
Returns a shared pointer to this vertex.
Definition: Tree.h:1081