Mercurial > code
changeset 365:93c8f8a1fd3f
Treenode:
- Extern Object for further usage
- Rename take to move
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 29 Apr 2015 09:54:54 +0200 |
parents | d88c3644ebc8 |
children | acb3192de1fb |
files | C++/modules/Treenode/TreeNode.h C++/tests/Treenode/main.cpp |
diffstat | 2 files changed, 100 insertions(+), 81 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/modules/Treenode/TreeNode.h Tue Apr 28 18:48:32 2015 +0200 +++ b/C++/modules/Treenode/TreeNode.h Wed Apr 29 09:54:54 2015 +0200 @@ -72,6 +72,69 @@ } // !namespace /** + * @class TreeNodeItem + * @brief Children object + * @see TreeNodeItemProxy + */ +template <typename T> +class TreeNodeItem { +public: + /** + * Get the real object as a reference. + */ + virtual T &value() = 0; + + /** + * Do a real polymorphic copy of the children object. + * + * @return a copy of the object + */ + virtual std::unique_ptr<TreeNodeItem<T>> clone() const = 0; +}; + +/** + * @class TreeNodeItemProxy + * @brief Implements polymorphic copy for the given value + */ +template <typename T, typename Value> +class TreeNodeItemProxy final : public TreeNodeItem<T> { +private: + Value m_value; + + TreeNodeItemProxy(const TreeNodeItemProxy &) = delete; + TreeNodeItemProxy &operator=(const TreeNodeItemProxy &) = delete; + TreeNodeItemProxy(TreeNodeItemProxy &&) = delete; + TreeNodeItemProxy &operator=(TreeNodeItemProxy &&) = delete; + +public: + inline TreeNodeItemProxy(Value &&value) + : m_value(std::move(value)) + { + } + + inline TreeNodeItemProxy(const Value &value) + : m_value(value) + { + } + + template <typename... Args> + inline TreeNodeItemProxy(Args&&... args) + : m_value(std::forward<Args>(args)...) + { + } + + T &value() override + { + return m_value; + } + + std::unique_ptr<TreeNodeItem<T>> clone() const override + { + return std::make_unique<TreeNodeItemProxy<T, Value>>(m_value); + } +}; + +/** * @class TreeNode * @brief Safe C++11 N-ary tree * @@ -80,52 +143,8 @@ */ template <typename T> class TreeNode { -private: - class Object { - public: - virtual T &get() = 0; - virtual std::unique_ptr<Object> clone() const = 0; - }; - - template <typename Value> - struct Proxy final : public Object { - private: - Value m_value; - - Proxy(const Proxy &) = delete; - Proxy &operator=(const Proxy &) = delete; - Proxy(Proxy &&) = delete; - Proxy &operator=(Proxy &&) = delete; - - public: - inline Proxy(Value &&value) - : m_value(std::move(value)) - { - } - - inline Proxy(const Value &value) - : m_value(value) - { - } - - template <typename... Args> - inline Proxy(Args&&... args) - : m_value(std::forward<Args>(args)...) - { - } - - T &get() override - { - return m_value; - } - - std::unique_ptr<Object> clone() const override - { - return std::make_unique<Proxy<Value>>(m_value); - } - }; - - using Container = std::deque<std::unique_ptr<Object>>; +public: + using Container = std::deque<std::unique_ptr<TreeNodeItem<T>>>; TreeNode *m_parent{nullptr}; Container m_children; @@ -151,7 +170,7 @@ { for (const auto &c : other.m_children) { m_children.push_back(c->clone()); - m_children.back()->get().m_parent = this; + m_children.back()->value().m_parent = this; } } @@ -166,7 +185,7 @@ { // Update children to update to *this for (auto &c : m_children) - c->get().m_parent = this; + c->value().m_parent = this; other.m_children.clear(); } @@ -182,7 +201,7 @@ for (const auto &c : other.m_children) { m_children.push_back(c->clone()); - m_children.back()->get().m_parent = this; + m_children.back()->value().m_parent = this; } return *this; @@ -199,7 +218,7 @@ // Update children to update to *this for (auto &c : m_children) - c->get().m_parent = this; + c->value().m_parent = this; other.m_children.clear(); @@ -214,8 +233,8 @@ template <typename Value> inline void push(const Value &child) { - m_children.push_front(std::make_unique<Proxy<Value>>(child)); - m_children.front()->get().m_parent = this; + m_children.push_front(std::make_unique<TreeNodeItemProxy<T, Value>>(child)); + m_children.front()->value().m_parent = this; } /** @@ -228,8 +247,8 @@ { using Type = typename std::decay<Value>::type; - m_children.push_front(std::make_unique<Proxy<Type>>(std::move(child))); - m_children.front()->get().m_parent = this; + m_children.push_front(std::make_unique<TreeNodeItemProxy<T, Type>>(std::move(child))); + m_children.front()->value().m_parent = this; } /** @@ -240,8 +259,8 @@ template <typename... Args> void pushNew(Args&&... args) { - m_children.emplace_front(std::make_unique<Proxy<T>>(std::forward<Args>(args)...)); - m_children.front()->get().m_parent = this; + m_children.emplace_front(std::make_unique<TreeNodeItemProxy<T, T>>(std::forward<Args>(args)...)); + m_children.front()->value().m_parent = this; } /** @@ -252,8 +271,8 @@ template <typename Value> inline void append(const Value &child) { - m_children.push_back(std::make_unique<Proxy<Value>>(child)); - m_children.back()->get().m_parent = this; + m_children.push_back(std::make_unique<TreeNodeItemProxy<T, Value>>(child)); + m_children.back()->value().m_parent = this; } /** @@ -266,8 +285,8 @@ { using Type = typename std::decay<Value>::type; - m_children.push_back(std::make_unique<Proxy<Type>>(std::move(child))); - m_children.back()->get().m_parent = this; + m_children.push_back(std::make_unique<TreeNodeItemProxy<T, Type>>(std::move(child))); + m_children.back()->value().m_parent = this; } /** @@ -278,8 +297,8 @@ template <typename... Args> void appendNew(Args&&... args) { - m_children.emplace_back(std::make_unique<Proxy<T>>(std::forward<Args>(args)...)); - m_children.back()->get().m_parent = this; + m_children.emplace_back(std::make_unique<TreeNodeItemProxy<T, T>>(std::forward<Args>(args)...)); + m_children.back()->value().m_parent = this; } /** @@ -364,7 +383,7 @@ void remove(T &value) { m_children.erase(std::remove_if(m_children.begin(), m_children.end(), [&] (auto &p) { - return &p->get() == &value; + return &p->value() == &value; }), m_children.end()); } @@ -378,7 +397,7 @@ void removeSame(const Value &value, typename std::enable_if<TypeTraits<Value>::equalityComparable>::type * = nullptr) { m_children.erase(std::remove_if(m_children.begin(), m_children.end(), [&] (auto &p) { - return p->get() == value; + return p->value() == value; }), m_children.end()); } @@ -400,7 +419,7 @@ int indexOf(const T &child) const noexcept { for (unsigned i = 0; i < m_children.size(); ++i) - if (&m_children[i]->get() == &child) + if (&m_children[i]->value() == &child) return i; return -1; @@ -417,7 +436,7 @@ int indexOfSame(const Value &value, typename std::enable_if<TypeTraits<Value>::equalityComparable>::type * = nullptr) const noexcept { for (unsigned i = 0; i < m_children.size(); ++i) - if (m_children[i]->get() == value) + if (m_children[i]->value() == value) return i; return -1; @@ -448,7 +467,7 @@ * @param other the other node to move, the node is emptied but may be reused * @param position position in that tree, -1 means end */ - inline void take(T &other, int position = -1) + inline void move(T &other, int position = -1) { if (other.m_parent == nullptr) { throw std::invalid_argument("can't move root node"); @@ -457,8 +476,8 @@ throw std::invalid_argument("attempt to move node to itself"); } - auto it = std::find_if(other.m_parent->m_children.begin(), other.m_parent->m_children.end(), [&] (const std::unique_ptr<Object> &object) -> bool { - return &object->get() == &other; + auto it = std::find_if(other.m_parent->m_children.begin(), other.m_parent->m_children.end(), [&] (const auto &object) -> bool { + return &object->value() == &other; }); if (it == other.m_parent->m_children.end()) { @@ -469,7 +488,7 @@ m_children.insert(m_children.begin() + position, std::move(*it)); other.m_parent->m_children.erase(it); - m_children[position]->get().m_parent = this; + m_children[position]->value().m_parent = this; } /** @@ -484,7 +503,7 @@ callback(static_cast<T &>(*this)); for (auto &v : m_children) - v->get().map(callback); + v->value().map(callback); } /** @@ -516,7 +535,7 @@ } for (auto &v : m_children) { - if (v->get().search(predicate, callable)) + if (v->value().search(predicate, callable)) return true; } @@ -554,7 +573,7 @@ */ T &operator[](int index) { - return static_cast<T &>(m_children.at(index)->get()); + return static_cast<T &>(m_children.at(index)->value()); } /** @@ -566,7 +585,7 @@ */ const T &operator[](int index) const { - return static_cast<const T &>(m_children.at(index)->get()); + return static_cast<const T &>(m_children.at(index)->value()); } };
--- a/C++/tests/Treenode/main.cpp Tue Apr 28 18:48:32 2015 +0200 +++ b/C++/tests/Treenode/main.cpp Wed Apr 29 09:54:54 2015 +0200 @@ -1493,10 +1493,10 @@ } /* -------------------------------------------------------- - * Take + * Move * -------------------------------------------------------- */ -TEST(Take, correct) +TEST(Move, correct) { Object root("a"); @@ -1505,7 +1505,7 @@ root[1].appendNew("d"); try { - root[0].take(root[1][0]); + root[0].move(root[1][0]); } catch (const std::exception &ex) { FAIL() << ex.what(); } @@ -1516,7 +1516,7 @@ ASSERT_TRUE(&root[0][0].parent() == &root[0]); } -TEST(Take, moveSelf) +TEST(Move, moveSelf) { Object root("a"); @@ -1524,14 +1524,14 @@ root.appendNew("c"); try { - root[0].take(root[0]); + root[0].move(root[0]); FAIL() << "Expected exception"; } catch (const std::exception &) { // SUCCESS } } -TEST(Take, moveRoot) +TEST(Move, moveRoot) { Object root("a"); @@ -1539,7 +1539,7 @@ root.appendNew("c"); try { - root[0].take(root); + root[0].move(root); FAIL() << "Expected exception"; } catch (const std::exception &) { // SUCCESS