8 #ifndef Sawyer_TreeVertex_H
9 #define Sawyer_TreeVertex_H
11 #include <Sawyer/Assert.h>
12 #include <Sawyer/Exception.h>
14 #include <boost/lexical_cast.hpp>
15 #include <boost/range/adaptor/reversed.hpp>
114 class Vertex:
public std::enable_shared_from_this<Vertex<B>> {
154 :
Exception(
"vertex is already attached to a tree", vertex) {}
164 :
Exception(
"insertion of vertex would cause a cycle in the tree", vertex) {}
226 explicit operator bool()
const {
227 return parent_ !=
nullptr;
232 template<
class T>
friend class Edge;
241 enum class Link { NO, YES };
251 virtual ~EdgeBase() {}
253 EdgeBase(
const EdgeBase&) =
delete;
254 EdgeBase& operator=(
const EdgeBase&) =
delete;
255 explicit EdgeBase(EdgeBase *prev)
259 virtual size_t size()
const = 0;
268 template<
class T,
class Visitor>
271 if (
auto retval = prev->traverse<T>(visitor))
274 for (
size_t i = 0; i < size(); ++i) {
276 if (
auto retval =
child->template traverse<T>(visitor))
321 class Edge:
public EdgeBase {
392 if (child != child_) {
393 checkChildInsertion(child);
397 child_->parent.reset();
403 child->parent.set(parent_);
411 return (*
this) =
parent();
416 explicit operator bool()
const {
417 return child_ !=
nullptr;
423 size_t size()
const override {
427 Vertex* pointer(
size_t i)
const override {
428 ASSERT_always_require(0 == i);
441 class EdgeVector:
public EdgeBase {
450 using Vector = std::vector<std::unique_ptr<Edge<Child>>>;
454 using size_type =
typename Vector::size_type;
455 using difference_type =
typename Vector::difference_type;
460 template<
class BaseIterator>
462 BaseIterator baseIterator_;
466 Iterator(
const BaseIterator &baseIterator)
467 : baseIterator_(baseIterator) {}
470 : baseIterator_(other.baseIterator_) {}
473 baseIterator_ = other.baseIterator_;
499 Iterator& operator+=(difference_type n) {
504 Iterator operator+(difference_type n)
const {
510 Iterator& operator-=(difference_type n) {
515 Iterator operator-(difference_type n)
const {
521 difference_type operator-(
const Iterator &other)
const {
522 return other.baseIterator_ - baseIterator_;
525 auto& operator*()
const {
526 ASSERT_not_null(*baseIterator_);
527 return **baseIterator_;
530 auto& operator->()
const {
531 ASSERT_not_null(*baseIterator_);
532 return &**baseIterator_;
535 auto& operator[](difference_type i)
const {
536 ASSERT_not_null(baseIterator_[i]);
537 return *baseIterator_[i];
540 bool operator==(
const Iterator &other)
const {
541 return baseIterator_ == other.baseIterator_;
544 bool operator!=(
const Iterator &other)
const {
545 return baseIterator_ != other.baseIterator_;
548 bool operator<(
const Iterator &other)
const {
549 return baseIterator_ < other.baseIterator_;
552 bool operator<=(
const Iterator &other)
const {
553 return baseIterator_ <= other.baseIterator_;
556 bool operator>(
const Iterator &other)
const {
557 return baseIterator_ > other.baseIterator_;
560 bool operator>=(
const Iterator &other)
const {
561 return baseIterator_ >= other.baseIterator_;
588 return edges_.empty();
595 return edges_.size();
605 return edges_.capacity();
613 auto edge = std::unique_ptr<Edge<Child>>(
new Edge<Child>(Link::NO, parent_, elmt));
614 edges_.push_back(std::move(edge));
621 ASSERT_forbid(edges_.empty());
629 ASSERT_require(i < edges_.size());
630 return *edges_.at(i);
633 ASSERT_require(i < edges_.size());
634 return *edges_.at(i);
648 ASSERT_forbid(
empty());
652 ASSERT_forbid(
empty());
661 ASSERT_forbid(
empty());
665 ASSERT_forbid(
empty());
681 Vertex* pointer(
size_t i)
const override {
682 return at(i)().
get();
695 EdgeBase *treeEdges_ =
nullptr;
698 virtual void destructorHelper() {}
709 std::shared_ptr<T>
isa();
742 template<
class T,
class Visitor>
744 auto vertex = std::dynamic_pointer_cast<T>(this->
pointer());
751 if (
auto result =
parent()->template traverseReverse<T>(visitor))
770 template<
class T,
class Visitor>
772 auto vertex = std::dynamic_pointer_cast<T>(this->
pointer());
778 if (
auto retval = treeEdges_->template traverse<T>(visitor))
795 template<
class T,
class Visitor>
797 return traverse<T>([&visitor] (
const std::shared_ptr<T> &vertex,
TraversalEvent event) {
799 return visitor(vertex);
801 return decltype(visitor(vertex))();
813 template<
class T,
class Visitor>
815 return traverse<T>([&visitor] (
const std::shared_ptr<T> &vertex,
TraversalEvent event) {
817 return visitor(vertex);
819 return decltype(visitor(vertex))();
827 return traverseReverse<T>([](
const std::shared_ptr<T> &vertex,
TraversalEvent event) {
835 return traverseReverse<T>([](
const std::shared_ptr<T> &vertex,
TraversalEvent event) {
846 std::vector<std::shared_ptr<T>> retval;
847 traverse<T>([&retval](
const std::shared_ptr<T> &vertex,
TraversalEvent event) {
849 retval.push_back(vertex);
872 ASSERT_require(this->parent_ ==
nullptr);
892 ASSERT_not_null(parent_);
893 return parent_->pointer();
899 return ptr.get() == parent_;
905 return ptr.get() != parent_;
911 return parent_ == other.parent_;
917 return parent_ != other.parent_;
924 return parent_ == other();
931 return parent_ != other();
960 : EdgeBase(parent.treeEdges_), parent_(parent) {
961 parent_.treeEdges_ =
this;
967 : EdgeBase(parent.treeEdges_), parent_(parent), child_(child) {
968 checkChildInsertion(child);
969 parent_.treeEdges_ =
this;
971 child->parent.set(parent);
977 : EdgeBase(Link::YES == link ? parent.treeEdges_ : nullptr), parent_(parent), child_(child) {
978 checkChildInsertion(child);
979 if (Link::YES == link)
980 parent_.treeEdges_ =
this;
982 child->parent.set(parent);
991 throw InsertionError(child);
993 for (
const UserBase *p = &parent_; p; p = p->parent().get()) {
994 if (p == child.get())
995 throw CycleError(child);
1003 const std::shared_ptr<T>&
1005 ASSERT_not_null(child_);
1011 const std::shared_ptr<T>&
1020 return child_ == ptr;
1027 return child_ != ptr;
1034 return child_ == other();
1041 return child_.get() != other();
1049 return child_.get() == other.get();
1057 return child_.get() != other.get();
1067 : EdgeBase(parent.treeEdges_), parent_(parent) {
1068 parent_.treeEdges_ =
this;
1082 auto retval = std::dynamic_pointer_cast<
UserBase>(this->shared_from_this());
1083 ASSERT_not_null(retval);
1091 return std::dynamic_pointer_cast<T>(this->shared_from_this());
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);
1114 for (
const EdgeBase *edge = treeEdges_; edge; edge = edge->prev)
size_t nChildren() const
Returns the number of children.
void push_back(const ChildPtr &elmt)
Insert a child pointer at the end of this vertex.
auto traverseReverse(const Visitor &visitor)
Traverse in reverse direction from children to parents.
Exception(const std::string &mesg, const UserBasePtr &vertex)
Construct a new error with the specified message and the causing vertex.
iterator end()
Return an iterator to one past the last edge.
std::shared_ptr< Child > ChildPtr
Type of pointers to children.
std::shared_ptr< Child > ChildPtr
Type of pointer to the child.
RuntimeError(const std::string &mesg)
Constructor taking a description of the error.
bool empty() const
Test whether vector is empty.
iterator begin()
Return an iterator to the first edge.
size_t capacity() const
Reserved capacity.
bool operator!=(const UserBasePtr &) const
Compare the child pointer to another pointer.
const ChildPtr & operator()() const
Return the child if there is one, else null.
Edge< Child > & back()
Return the last edge.
EdgeVector(UserBase &parent)
Construct a child edge that belongs to the specified parent.
A parent-to-child edge in a tree.
void pop_back()
Erase a child edge from the end of this vertex.
std::shared_ptr< T > findLastAncestor()
Traversal that finds the farthest ancestor of type T or derived from T.
Edge< Child > & operator[](size_t i)
Return the i'th edge.
const Edge< Child > & front() const
Return the first edge.
InsertionError(const UserBasePtr &vertex)
Construct a new error with the vertex that caused the error.
Edge & operator=(const ChildPtr &child)
Assign a pointer to a child.
const Edge< Child > & operator[](size_t i) const
Return the i'th edge.
Base class for Sawyer runtime errors.
CycleError(const UserBasePtr &vertex)
Construct a new error with the vertex that caused the error.
UserBasePtr vertex
Vertex that caused the error.
Name space for the entire library.
Error when attaching a vertex to a tree and the vertex is already attached somewhere else...
Edge(UserBase &parent)
Construct a child edge that belongs to the specified parent.
const Edge< Child > & at(size_t i) const
Return the i'th edge.
Edge< Child > & at(size_t i)
Return the i'th edge.
std::shared_ptr< UserBase > UserBasePtr
Pointer to user's base class.
~EdgeVector()
Destructor clears children's parents.
Edge< Child > & front()
Return the first edge.
ReverseEdge parent
Pointer to the parent in the tree.
std::shared_ptr< T > isa()
Tests whether this object is a certain type.
~Edge()
Destructor clears child's parent.
Edge & operator=(const ReverseEdge &parent)
Assign a pointer to a child.
void reserve(size_t n)
Reserve space so the child edge vector can grow without being reallocated.
UserBasePtr child(size_t i) const
Returns the pointer for a child.
TraversalEvent
Traversal event.
Node UserBase
User's base class.
Base class for tree vertices.
Base class for errors and exceptions for this vertex type.
Error when attaching a vertex to a tree would cause a cycle.
bool operator==(const UserBasePtr &) const
Compare the child pointer to another pointer.
auto traversePre(const Visitor &visitor)
Pre-order forward traversal.
auto traverse(const Visitor &visitor)
Traverse in forward direction from parents to children.
bool operator!=(const UserBasePtr &) const
Compare the parent pointer to another pointer.
bool operator==(const UserBasePtr &) const
Compare the parent pointer to another pointer.
UserBasePtr operator->() const
Return the parent if there is one, else null.
const Edge< Child > & back() const
Return the last edge.
size_t size() const override
Number of child edges.
A 1:N tree edge from parent to children.
const ChildPtr & operator->() const
Return the child if there is one, else null.
T Child
Type of children being pointed to.
std::shared_ptr< T > findFirstAncestor()
Traversal that finds the closest ancestor of type T or derived from T.
T Child
Type of child being pointed to.
UserBasePtr operator()() const
Return the parent if there is one, else null.
std::vector< std::shared_ptr< T > > findDescendants()
Traversal that finds all the descendants of a particular type.
auto traversePost(const Visitor &visitor)
Post-order forward traversal.
Points from a child to a parent in the tree.
UserBasePtr pointer()
Returns a shared pointer to this vertex.