Mercurial > code
view C++/TreeNode.h @ 233:29eb8748b686
Add TreeNode, a N-ary tree implementation without pointers
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 24 Jun 2014 17:19:03 +0200 |
parents | |
children | 99f8b9aedfb3 |
line wrap: on
line source
/* * TreeNode.h -- C++11 pointer-free N-ary tree * * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _TREE_NODE_H_ #define _TREE_NODE_H_ /** * @file TreeNode.h * @brief N-ary tree without pointers */ #include <algorithm> #include <stdexcept> #include <vector> /** * @class TreeNode * @brief Safe C++11 N-ary tree * * This class template can be used to implement N-ary trees without any pointers. It uses * move semantics and copy constructs to avoid usage of pointers. * * The typename T must be at least one of the following requirement: * - CopyConstructible * - MoveConstructible */ template <typename T, typename Container = std::vector<T>> class TreeNode { private: TreeNode *m_parent = nullptr; Container m_children; /* * This is used by move constructors and assignment. It removes the * reference to the object in the old tree. */ inline void updateOther(TreeNode &&other) { if (other.m_parent) { auto &children = other.m_parent->m_children; auto finder = [&] (TreeNode &i) { return &other == &i; }; children.erase(std::find_if(children.begin(), children.end(), finder)); } other.m_parent = nullptr; } public: /** * Default constructor. */ TreeNode() = default; /** * Copy constructor. * * @param other the other node */ TreeNode(const TreeNode &other) : TreeNode() { m_children = other.m_children; for (auto &c : m_children) c.m_parent = this; } /** * Move constructor. * * @param other the other node */ TreeNode(TreeNode &&other) : TreeNode() { m_children = std::move(other.m_children); updateOther(std::move(other)); for (auto &c : m_children) c.m_parent = this; } /** * Copy assignment operator. * * @param other the other node */ TreeNode &operator=(const TreeNode &other) { m_parent = nullptr; m_children = other.m_children; for (auto &c : m_children) c.m_parent = this; } /** * Move assignment operator. * * @param other the other node */ TreeNode &operator=(TreeNode &&other) { m_parent = nullptr; m_children = std::move(other.m_children); updateOther(std::move(other)); for (auto &c : m_children) c.m_parent = this; return *this; } /** * Add a child node. * * @param child the children */ void add(const T &child) { m_children.push_back(child); m_children.back().m_parent = this; } /** * Move a child node. * * @param child the child */ void add(T &&child) { m_children.push_back(std::move(child)); m_children.back().m_parent = this; } /** * Count the number of children in this node. * * @return the number of children */ unsigned countChildren() const { return static_cast<unsigned>(m_children.size()); } /** * Get the parent node. * * @return the parent node * @throw std::out_of_range if there is no parent */ T &parent() { if (!m_parent) throw std::out_of_range("no parent"); return static_cast<T &>(*m_parent); } /** * Get the parent node. * * @return the parent node * @throw std::out_of_range if there is no parent */ const T &parent() const { if (!m_parent) throw std::out_of_range("no parent"); return static_cast<const T &>(*m_parent); } /** * Check if the node is root (no parent). * * @return true if root */ bool isRoot() const { return m_parent == nullptr; } /** * Check if the node is leaf (no children). * * @return true if leaf */ bool isLeaf() const { return m_children.size() == 0; } /** * Access a children. * * @param index the index * @return the reference to the children node * @throw std::out_of_range on out of bounds */ T &operator[](int index) { return static_cast<T &>(m_children.at(index)); } /** * Access a children. * * @param index the index * @return the reference to the children node * @throw std::out_of_range on out of bounds */ const T &operator[](int index) const { return static_cast<const T &>(m_children.at(index)); } }; #endif // !_TREE_NODE_H_