diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f5c0b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.swp +build +.vscode diff --git a/include/ifaces/ILink.h b/include/ifaces/ILink.h index 20d51a7..c77b0fb 100644 --- a/include/ifaces/ILink.h +++ b/include/ifaces/ILink.h @@ -10,11 +10,11 @@ using LinkPtr = std::shared_ptr; class ILink { public: - virtual ~ILink() = default; - virtual NodePtr getNode() const = 0; - virtual LinkPtr getParent() const = 0; - virtual void setParent(const LinkPtr& parent) = 0; - virtual const std::vector& getChildren() const = 0; - virtual void addChild(const LinkPtr& child) = 0; - virtual void removeChild(const LinkPtr& child) = 0; + virtual ~ILink() = default; + virtual NodePtr getNode() const = 0; + virtual NodePtr getParent() const = 0; + virtual void setParent(const NodePtr& parent) = 0; + virtual const std::vector& getChildren() const = 0; + virtual void addChild(const NodePtr& child) = 0; + virtual void removeChild(const NodePtr& child) = 0; }; diff --git a/include/ifaces/ILinkMixin.h b/include/ifaces/ILinkMixin.h index 3d7bb95..4fd59ef 100644 --- a/include/ifaces/ILinkMixin.h +++ b/include/ifaces/ILinkMixin.h @@ -9,8 +9,9 @@ using LinkPtr = std::shared_ptr; class ILinkMixin { public: - virtual ~ILinkMixin() = default; - virtual void linkChild(const NodePtr& child) = 0; - virtual void unlinkParent() = 0; - virtual LinkPtr getLink() = 0; + virtual ~ILinkMixin() = default; + virtual void linkChild(const NodePtr& child) = 0; + virtual void unlinkParent() = 0; + virtual LinkPtr getLink() = 0; + virtual NodePtr getSelf() = 0; }; diff --git a/include/ifaces/INode.h b/include/ifaces/INode.h index 7019bb9..9ebbc70 100644 --- a/include/ifaces/INode.h +++ b/include/ifaces/INode.h @@ -5,7 +5,7 @@ // INode является ILinkMixin, поэтому полный #include здесь оправдан class INode : public ILinkMixin { public: - ~INode() override = default; - virtual const std::string& name() const = 0; - virtual NodePtr getSelf() = 0; + ~INode() override = default; + virtual const std::string& name() const = 0; + virtual NodePtr getSelf() = 0; }; diff --git a/include/links/BaseLink.h b/include/links/BaseLink.h index d57b5ce..c6839c3 100644 --- a/include/links/BaseLink.h +++ b/include/links/BaseLink.h @@ -5,20 +5,20 @@ class BaseLink : public ILink { public: - explicit BaseLink(NodePtr node) : owner_node_(node) {} - NodePtr getNode() const override { return owner_node_.lock(); } - LinkPtr getParent() const override { return parent_.lock(); } - void setParent(const LinkPtr& parent) override { parent_ = parent; } - const std::vector& getChildren() const override { return children_; } - void removeChild(const LinkPtr& child) override { - children_.erase(std::remove(children_.begin(), children_.end(), child), children_.end()); - } + explicit BaseLink(NodePtr node) : owner_node_(node) {} + NodePtr getNode() const override { return owner_node_.lock(); } + NodePtr getParent() const override { return parent_.lock(); } + void setParent(const NodePtr& parent) override { parent_ = parent; } + const std::vector& getChildren() const override { return children_; } + void removeChild(const NodePtr& child) override { + children_.erase(std::remove(children_.begin(), children_.end(), child), children_.end()); + } - ~BaseLink() override { - std::cout << "--- Destructor called for: " << "BaseLink" << "\n"; - } + ~BaseLink() override { + std::cout << "--- Destructor called for: " << "BaseLink" << "\n"; + } protected: - std::vector children_; - std::weak_ptr owner_node_; - std::weak_ptr parent_; + std::vector children_; + std::weak_ptr owner_node_; + std::weak_ptr parent_; }; diff --git a/include/links/LeafLink.h b/include/links/LeafLink.h index ba490fb..081f44e 100644 --- a/include/links/LeafLink.h +++ b/include/links/LeafLink.h @@ -4,6 +4,6 @@ class LeafLink : public BaseLink { public: - using BaseLink::BaseLink; - void addChild(const LinkPtr&) override { throw std::logic_error("LeafLink cannot have children"); } + using BaseLink::BaseLink; + void addChild(const NodePtr&) override { throw std::logic_error("LeafLink cannot have children"); } }; diff --git a/include/links/OneToManyLink.h b/include/links/OneToManyLink.h index 6c371b6..1e65957 100644 --- a/include/links/OneToManyLink.h +++ b/include/links/OneToManyLink.h @@ -3,6 +3,6 @@ class OneToManyLink : public BaseLink { public: - using BaseLink::BaseLink; - void addChild(const LinkPtr& child) override { children_.push_back(child); } + using BaseLink::BaseLink; + void addChild(const NodePtr& child) override { children_.push_back(child); } }; diff --git a/include/mixins/LazyLinkMixin.h b/include/mixins/LazyLinkMixin.h index 9d0e47a..9091901 100644 --- a/include/mixins/LazyLinkMixin.h +++ b/include/mixins/LazyLinkMixin.h @@ -5,67 +5,50 @@ #include "links/OneToManyLink.h" #include -template -class LazyLinkMixin : public INode { +template +class LazyLinkMixin : public ILinkMixin { public: - void linkChild(const NodePtr& childNode) override { - lazyInit(); - upgradeLinkIfNeeded(); - LinkPtr childLink = childNode->getLink(); - childLink->setParent(link_); - link_->addChild(childLink); - } + void linkChild(const NodePtr& childNode) override { + LinkPtr childLink = childNode->getLink(); + childLink->setParent(getSelf()); - void unlinkParent() override { - lazyInit(); - LinkPtr parentLink = link_->getParent(); - if (!parentLink) return; - parentLink->removeChild(this->getLink()); - link_->setParent(nullptr); - } + getLink()->addChild(childNode); + } - LinkPtr getLink() override { - lazyInit(); - return link_; - } + void unlinkParent() override { + /* No link -- no parent, who'll unlinked? */ + if (!link_) + throw std::logic_error("Link isn't inited!"); - ~LazyLinkMixin() override { - std::cout << "--- Destructor called for: " << "LazyLinkMixin" << "\n"; - } + NodePtr parent = link_->getParent(); + if (!parent) + throw std::logic_error("Have no parent!"); -protected: - virtual std::shared_ptr getShared() = 0; - NodePtr getSelf() override { return getShared(); } + LinkPtr parentLink = parent->getLink(); -private: - void lazyInit() { - if (!link_) { - link_ = std::make_shared(getSelf()); - } - } + parentLink->removeChild(getSelf()); + getLink()->setParent(nullptr); + } + + LinkPtr getLink() override { + lazyInit(); + return link_; + } - void upgradeLinkIfNeeded() { - if (!std::dynamic_pointer_cast(link_)) return; - auto newLink = std::make_shared(getSelf()); - if (auto parentLink = link_->getParent()) { - parentLink->removeChild(link_); - parentLink->addChild(newLink); - } - newLink->setParent(link_->getParent()); - link_ = newLink; - } + ~LazyLinkMixin() override { + std::cout << "--- Destructor called for: " << "LazyLinkMixin" << "\n"; + } - void downgradeLinkIfPossible() { - if (link_->getChildren().empty() && std::dynamic_pointer_cast(link_)) { - auto newLink = std::make_shared(getSelf()); - if (auto parentLink = link_->getParent()) { - parentLink->removeChild(link_); - parentLink->addChild(newLink); - } - newLink->setParent(link_->getParent()); - link_ = newLink; - } - } +protected: + virtual NodePtr getShared() = 0; + NodePtr getSelf() override { return getShared(); } + +private: + void lazyInit() { + if (!link_) { + link_ = std::make_shared(getSelf()); + } + } - LinkPtr link_; + LinkPtr link_; }; diff --git a/include/nodes/BaseNode.h b/include/nodes/BaseNode.h new file mode 100644 index 0000000..c03894d --- /dev/null +++ b/include/nodes/BaseNode.h @@ -0,0 +1,20 @@ +#pragma once +#include "mixins/LazyLinkMixin.h" +#include "ifaces/INode.h" +#include + +class BaseNode : public INode, + public LazyLinkMixin, + public std::enable_shared_from_this { +public: + BaseNode(std::string name) : name_(std::move(name)) {} + const std::string& name() const override { return name_; } + ~BaseNode() { + std::cout << "--- Destructor called for: " << name_ << "\n"; + } +protected: + NodePtr getShared() override { + return shared_from_this(); + } + std::string name_; +}; diff --git a/include/nodes/SimpleNode.h b/include/nodes/SimpleNode.h index 8e501df..816d6fd 100644 --- a/include/nodes/SimpleNode.h +++ b/include/nodes/SimpleNode.h @@ -1,26 +1,12 @@ #pragma once -#include "mixins/LazyLinkMixin.h" +#include "nodes/BaseNode.h" #include -class SimpleNode : public LazyLinkMixin, - public std::enable_shared_from_this { +class SimpleNode : + public BaseNode { public: - static NodePtr create(std::string name) { - struct EnableMakeShared : public SimpleNode { - EnableMakeShared(std::string n) : SimpleNode(std::move(n)) {} - }; - return std::make_shared(std::move(name)); - } - const std::string& name() const override { return name_; } - ~SimpleNode() { - std::cout << "--- Destructor called for: " << name_ << "\n"; - } -protected: - std::shared_ptr getShared() override { - return shared_from_this(); - } -private: - friend class LazyLinkMixin; - explicit SimpleNode(std::string name) : name_(std::move(name)) {} - std::string name_; + ~SimpleNode() { + std::cout << "--- Destructor called for: " << name_ << "\n"; + } + SimpleNode(std::string name) : BaseNode(std::move(name)) {} }; diff --git a/src/main.cpp b/src/main.cpp index cba1e65..b7eded3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,50 +2,50 @@ #include void printTree(const NodePtr& startNode, int indent = 0) { - if (!startNode) return; - for (int i = 0; i < indent; ++i) std::cout << " "; - std::cout << startNode->name() << "\n"; - LinkPtr nodeLink = startNode->getLink(); - for (const auto& childLink : nodeLink->getChildren()) { - printTree(childLink->getNode(), indent + 1); - } + if (!startNode) return; + for (int i = 0; i < indent; ++i) std::cout << " "; + std::cout << startNode->name() << "\n"; + LinkPtr nodeLink = startNode->getLink(); + for (const auto& child : nodeLink->getChildren()) { + printTree(child, indent + 1); + } } int main() { - std::cout << "Entering main scope...\n\n"; - - // Начало новой области видимости - { - auto root = SimpleNode::create("Root"); - auto child2 = SimpleNode::create("Child2"); - - root->linkChild(child2); + std::cout << "Entering main scope...\n\n"; + // Начало новой области видимости { - auto child1 = SimpleNode::create("Child1"); - root->linkChild(child1); - auto subchild = SimpleNode::create("SubChild"); - child1->linkChild(subchild); - auto child3 = SimpleNode::create("Child3"); - root->linkChild(child3); - auto subchild2 = SimpleNode::create("SubChild2"); - child3->linkChild(subchild2); - - std::cout << "Initial tree:\n"; + auto root = std::make_shared("Root"); + auto child2 = std::make_shared("Child2"); + + root->linkChild(child2); + + { + auto child1 = std::make_shared("Child1"); + root->linkChild(child1); + auto subchild = std::make_shared("SubChild"); + child1->linkChild(subchild); + auto child3 = std::make_shared("Child3"); + root->linkChild(child3); + auto subchild2 = std::make_shared("SubChild2"); + child3->linkChild(subchild2); + + std::cout << "Initial tree:\n"; + printTree(root); + + std::cout << "\nUnlinking Child1...\n"; + child1->unlinkParent(); + std::cout << "\nTree after unlink:\n"; + printTree(root); + } + + std::cout << "\nTree after scope out:\n"; printTree(root); - std::cout << "\nUnlinking Child1...\n"; - child1->unlinkParent(); - std::cout << "\nTree after unlink:\n"; - printTree(root); - } - - std::cout << "\nTree after scope out:\n"; - printTree(root); - - } // <--- КОНЕЦ ОБЛАСТИ ВИДИМОСТИ + } // <--- КОНЕЦ ОБЛАСТИ ВИДИМОСТИ - std::cout << "\nExited main scope. All smart pointers destroyed.\n"; + std::cout << "\nExited main scope. All smart pointers destroyed.\n"; - return 0; + return 0; }