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