changeset 366:acb3192de1fb

Treenode: - Rename countChildren -> childrenCount - Inline short functions - Add itemAt, pushItem, appendItem
author David Demelier <markand@malikania.fr>
date Wed, 29 Apr 2015 10:32:31 +0200
parents 93c8f8a1fd3f
children 99484c154d8a
files C++/modules/Treenode/TreeNode.h C++/tests/Treenode/main.cpp
diffstat 2 files changed, 280 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Treenode/TreeNode.h	Wed Apr 29 09:54:54 2015 +0200
+++ b/C++/modules/Treenode/TreeNode.h	Wed Apr 29 10:32:31 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * TreeNode.h -- C++11 pointer-free N-ary tree
+ * TreeNode.h -- C++14 pointer-free N-ary tree
  *
  * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
  *
@@ -21,7 +21,7 @@
 
 /**
  * @file TreeNode.h
- * @brief N-ary tree without pointers
+ * @brief N-ary polymorphic tree without pointers
  */
 
 #include <algorithm>
@@ -82,7 +82,7 @@
 	/**
 	 * Get the real object as a reference.
 	 */
-	virtual T &value() = 0;
+	virtual T &value() noexcept = 0;
 
 	/**
 	 * Do a real polymorphic copy of the children object.
@@ -96,7 +96,7 @@
  * @class TreeNodeItemProxy
  * @brief Implements polymorphic copy for the given value
  */
-template <typename T, typename Value>
+template <typename T, typename Value = T>
 class TreeNodeItemProxy final : public TreeNodeItem<T> {
 private:
 	Value m_value;
@@ -107,27 +107,48 @@
 	TreeNodeItemProxy &operator=(TreeNodeItemProxy &&) = delete;
 
 public:
-	inline TreeNodeItemProxy(Value &&value)
+	/**
+	 * Move the value.
+	 *
+	 * @param value the value
+	 */
+	inline TreeNodeItemProxy(Value &&value) noexcept
 		: m_value(std::move(value))
 	{
 	}
 
+	/**
+	 * Copy the value.
+	 *
+	 * @param value the value
+	 */
 	inline TreeNodeItemProxy(const Value &value)
 		: m_value(value)
 	{
 	}
 
+	/**
+	 * Construct the value in-place.
+	 *
+	 * @param args the arguments
+	 */
 	template <typename... Args>
 	inline TreeNodeItemProxy(Args&&... args)
 		: m_value(std::forward<Args>(args)...)
 	{
 	}
 
-	T &value() override
+	/**
+	 * @copydoc TreeNodeItem::value
+	 */
+	T &value() noexcept override
 	{
 		return m_value;
 	}
 
+	/**
+	 * @copydoc TreeNodeItem::clone
+	 */
 	std::unique_ptr<TreeNodeItem<T>> clone() const override
 	{
 		return std::make_unique<TreeNodeItemProxy<T, Value>>(m_value);
@@ -136,10 +157,12 @@
 
 /**
  * @class TreeNode
- * @brief Safe C++11 N-ary tree
+ * @brief Safe C++14 N-ary polymorphic tree
  *
  * This class use a std::deque as the container, it allocate object on the heap to avoid useless
  * copy and move when adding new elements.
+ *
+ * It also supports real polymorphic copies.
  */
 template <typename T>
 class TreeNode {
@@ -226,6 +249,17 @@
 	}
 
 	/**
+	 * Push an already allocated item.
+	 *
+	 * @param value the value to take
+	 */
+	inline void pushItem(std::unique_ptr<TreeNodeItem<T>> value)
+	{
+		m_children.push_front(std::move(value));
+		m_children.front()->value().m_parent = this;
+	}
+
+	/**
 	 * Add a child node to the beginning.
 	 *
 	 * @param child the children
@@ -257,13 +291,24 @@
 	 * @param args the arguments
 	 */
 	template <typename... Args>
-	void pushNew(Args&&... args)
+	inline void pushNew(Args&&... args)
 	{
-		m_children.emplace_front(std::make_unique<TreeNodeItemProxy<T, T>>(std::forward<Args>(args)...));
+		m_children.emplace_front(std::make_unique<TreeNodeItemProxy<T>>(std::forward<Args>(args)...));
 		m_children.front()->value().m_parent = this;
 	}
 
 	/**
+	 * Append an already allocated item.
+	 *
+	 * @param value the value to take
+	 */
+	inline void appendItem(std::unique_ptr<TreeNodeItem<T>> value)
+	{
+		m_children.push_back(std::move(value));
+		m_children.back()->value().m_parent = this;
+	}
+
+	/**
 	 * Add a child node to the end
 	 *
 	 * @param child the children
@@ -295,9 +340,9 @@
 	 * @param args the arguments
 	 */
 	template <typename... Args>
-	void appendNew(Args&&... args)
+	inline void appendNew(Args&&... args)
 	{
-		m_children.emplace_back(std::make_unique<TreeNodeItemProxy<T, T>>(std::forward<Args>(args)...));
+		m_children.emplace_back(std::make_unique<TreeNodeItemProxy<T>>(std::forward<Args>(args)...));
 		m_children.back()->value().m_parent = this;
 	}
 
@@ -306,7 +351,7 @@
 	 *
 	 * @return the number of children
 	 */
-	unsigned countChildren() const noexcept
+	inline unsigned childrenCount() const noexcept
 	{
 		return static_cast<unsigned>(m_children.size());
 	}
@@ -317,7 +362,7 @@
 	 * @return the parent node
 	 * @throw std::out_of_range if there is no parent
 	 */
-	T &parent()
+	inline T &parent()
 	{
 		if (!m_parent)
 			throw std::out_of_range("no parent");
@@ -331,7 +376,7 @@
 	 * @return the parent node
 	 * @throw std::out_of_range if there is no parent
 	 */
-	const T &parent() const
+	inline const T &parent() const
 	{
 		if (!m_parent)
 			throw std::out_of_range("no parent");
@@ -344,7 +389,7 @@
 	 *
 	 * @return true if root
 	 */
-	bool isRoot() const noexcept
+	inline bool isRoot() const noexcept
 	{
 		return m_parent == nullptr;
 	}
@@ -354,7 +399,7 @@
 	 *
 	 * @return true if leaf
 	 */
-	bool isLeaf() const noexcept
+	inline bool isLeaf() const noexcept
 	{
 		return m_children.size() == 0;
 	}
@@ -365,7 +410,7 @@
 	 * @param index the position index
 	 * @throw std::out_of_range if index is out of bounds
 	 */
-	void remove(int index)
+	inline void remove(int index)
 	{
 		if (index < 0 || index >= static_cast<int>(m_children.size()))
 			throw std::out_of_range("index is out of range");
@@ -380,7 +425,7 @@
 	 * @param value the value that exists in the node
 	 * @warn the removed object must not be used after the call
 	 */
-	void remove(T &value)
+	inline void remove(T &value)
 	{
 		m_children.erase(std::remove_if(m_children.begin(), m_children.end(), [&] (auto &p) {
 			return &p->value() == &value;
@@ -394,7 +439,7 @@
 	 * @warn the removed object must not be used after the call
 	 */
 	template <typename Value>
-	void removeSame(const Value &value, typename std::enable_if<TypeTraits<Value>::equalityComparable>::type * = nullptr)
+	inline 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->value() == value;
@@ -404,7 +449,7 @@
 	/**
 	 * Remove all children.
 	 */
-	void clear()
+	inline void clear()
 	{
 		m_children.clear();
 	}
@@ -498,7 +543,7 @@
 	 * @param callback the callback
 	 */
 	template <typename Callback>
-	void map(Callback callback)
+	inline void map(Callback callback)
 	{
 		callback(static_cast<T &>(*this));
 
@@ -512,7 +557,7 @@
 	 * @param dest the destination iterator
 	 */
 	template <typename OutputIt>
-	void flat(OutputIt dest)
+	inline void flat(OutputIt dest)
 	{
 		map([&] (const auto &value) {
 			*dest++ = value;
@@ -565,13 +610,47 @@
 	}
 
 	/**
+	 * Access a child as the node item.
+	 *
+	 * @warning the object is moved, thus empty
+	 * @param index the index
+	 * @throw std::out_of_range on out of bounds
+	 */
+	inline std::unique_ptr<TreeNodeItem<T>> itemAt(int index) &&
+	{
+		return std::move(m_children.at(index));
+	}
+
+	/**
+	 * Access a child as the node item.
+	 *
+	 * @param index the index
+	 * @throw std::out_of_range on out of bounds
+	 */
+	inline std::unique_ptr<TreeNodeItem<T>> &itemAt(int index) &
+	{
+		return m_children.at(index);
+	}
+
+	/**
+	 * Access a child as the node item.
+	 *
+	 * @param index the index
+	 * @throw std::out_of_range on out of bounds
+	 */
+	inline const std::unique_ptr<TreeNodeItem<T>> &itemAt(int index) const &
+	{
+		return m_children.at(index);
+	}
+
+	/**
 	 * Access a child.
 	 *
 	 * @param index the index
 	 * @return the reference to the children node
 	 * @throw std::out_of_range on out of bounds
 	 */
-	T &operator[](int index)
+	inline T &operator[](int index)
 	{
 		return static_cast<T &>(m_children.at(index)->value());
 	}
@@ -583,7 +662,7 @@
 	 * @return the reference to the children node
 	 * @throw std::out_of_range on out of bounds
 	 */
-	const T &operator[](int index) const
+	inline const T &operator[](int index) const
 	{
 		return static_cast<const T &>(m_children.at(index)->value());
 	}
--- a/C++/tests/Treenode/main.cpp	Wed Apr 29 09:54:54 2015 +0200
+++ b/C++/tests/Treenode/main.cpp	Wed Apr 29 10:32:31 2015 +0200
@@ -54,7 +54,7 @@
  *
  * ASSERT_(TRUE|FALSE) isRoot()
  * ASSERT_(TRUE|FALSE) isLeaf()
- * ASSERT_EQ countChildren()
+ * ASSERT_EQ childrenCount()
  * ASSERT_EQ() name()
  * ASSERT_TRUE & addresses
  */
@@ -72,7 +72,7 @@
 
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_TRUE(object.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 }
 
@@ -91,7 +91,7 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(1, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(1, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test moved a
@@ -103,7 +103,7 @@
 	// test original a
 	ASSERT_TRUE(a.isRoot());
 	ASSERT_TRUE(a.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(a.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(a.childrenCount()));
 }
 
 /*
@@ -121,7 +121,7 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(1, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(1, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test copied b
@@ -133,7 +133,7 @@
 	// test original b
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_TRUE(copy.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("b", copy.name());
 }
 
@@ -154,13 +154,13 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test moved 1
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("1", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
@@ -168,18 +168,18 @@
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_TRUE(object[1].isLeaf());
 	ASSERT_EQ("2", object[1].name());
-	ASSERT_EQ(0, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1].childrenCount()));
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test original 1
 	ASSERT_TRUE(o1.isRoot());
 	ASSERT_TRUE(o1.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o1.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o1.childrenCount()));
 
 	// test original 2
 	ASSERT_TRUE(o2.isRoot());
 	ASSERT_TRUE(o2.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o2.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o2.childrenCount()));
 }
 
 /*
@@ -199,33 +199,33 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test copied 1
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("1", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test copied 2
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_TRUE(object[1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1].childrenCount()));
 	ASSERT_EQ("2", object[1].name());
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test original 1
 	ASSERT_TRUE(o1.isRoot());
 	ASSERT_TRUE(o1.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o1.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o1.childrenCount()));
 	ASSERT_EQ("1", o1.name());
 
 	// test original 2
 	ASSERT_TRUE(o2.isRoot());
 	ASSERT_TRUE(o2.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o2.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o2.childrenCount()));
 	ASSERT_EQ("2", o2.name());
 }
 
@@ -244,20 +244,20 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(1, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(1, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("a", object[0].name());
 
 	// test moved a
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("a", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test original a
 	ASSERT_TRUE(a.isRoot());
 	ASSERT_TRUE(a.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(a.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(a.childrenCount()));
 }
 
 /*
@@ -275,20 +275,20 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(1, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(1, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("a", object[0].name());
 
 	// test copied a
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("a", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test original b
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_TRUE(copy.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("a", copy.name());
 }
 
@@ -309,13 +309,13 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test moved 2
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("2", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
@@ -323,18 +323,18 @@
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_TRUE(object[1].isLeaf());
 	ASSERT_EQ("1", object[1].name());
-	ASSERT_EQ(0, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1].childrenCount()));
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test original 1
 	ASSERT_TRUE(o1.isRoot());
 	ASSERT_TRUE(o1.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o1.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o1.childrenCount()));
 
 	// test original 2
 	ASSERT_TRUE(o2.isRoot());
 	ASSERT_TRUE(o2.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o2.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o2.childrenCount()));
 }
 
 /*
@@ -354,33 +354,33 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test copied 2
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_TRUE(object[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("2", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test copied 1
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_TRUE(object[1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1].childrenCount()));
 	ASSERT_EQ("1", object[1].name());
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test original 1
 	ASSERT_TRUE(o1.isRoot());
 	ASSERT_TRUE(o1.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o1.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o1.childrenCount()));
 	ASSERT_EQ("1", o1.name());
 
 	// test original 2
 	ASSERT_TRUE(o2.isRoot());
 	ASSERT_TRUE(o2.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(o2.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(o2.childrenCount()));
 	ASSERT_EQ("2", o2.name());
 }
 
@@ -411,48 +411,48 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test a
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_FALSE(object[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("a", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test b
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_FALSE(object[1].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object[1].childrenCount()));
 	ASSERT_EQ("b", object[1].name());
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test c
 	ASSERT_FALSE(object[0][0].isRoot());
 	ASSERT_TRUE(object[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0][0].childrenCount()));
 	ASSERT_EQ("c", object[0][0].name());
 	ASSERT_TRUE(&object[0] == &object[0][0].parent());
 
 	// test d
 	ASSERT_FALSE(object[0][1].isRoot());
 	ASSERT_TRUE(object[0][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0][1].childrenCount()));
 	ASSERT_EQ("d", object[0][1].name());
 	ASSERT_TRUE(&object[0] == &object[0][1].parent());
 
 	// test e
 	ASSERT_FALSE(object[1][0].isRoot());
 	ASSERT_TRUE(object[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1][0].childrenCount()));
 	ASSERT_EQ("e", object[1][0].name());
 	ASSERT_TRUE(&object[1] == &object[1][0].parent());
 
 	// test f
 	ASSERT_FALSE(object[1][1].isRoot());
 	ASSERT_TRUE(object[1][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1][1].childrenCount()));
 	ASSERT_EQ("f", object[1][1].name());
 	ASSERT_TRUE(&object[1] == &object[1][1].parent());
 }
@@ -480,48 +480,48 @@
 	// test root
 	ASSERT_TRUE(object.isRoot());
 	ASSERT_FALSE(object.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object.childrenCount()));
 	ASSERT_EQ("root", object.name());
 
 	// test b
 	ASSERT_FALSE(object[0].isRoot());
 	ASSERT_FALSE(object[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object[0].childrenCount()));
 	ASSERT_EQ("b", object[0].name());
 	ASSERT_TRUE(&object == &object[0].parent());
 
 	// test a
 	ASSERT_FALSE(object[1].isRoot());
 	ASSERT_FALSE(object[1].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(object[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(object[1].childrenCount()));
 	ASSERT_EQ("a", object[1].name());
 	ASSERT_TRUE(&object == &object[1].parent());
 
 	// test d
 	ASSERT_FALSE(object[0][0].isRoot());
 	ASSERT_TRUE(object[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0][0].childrenCount()));
 	ASSERT_EQ("d", object[0][0].name());
 	ASSERT_TRUE(&object[0] == &object[0][0].parent());
 
 	// test c
 	ASSERT_FALSE(object[0][1].isRoot());
 	ASSERT_TRUE(object[0][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[0][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[0][1].childrenCount()));
 	ASSERT_EQ("c", object[0][1].name());
 	ASSERT_TRUE(&object[0] == &object[0][1].parent());
 
 	// test f
 	ASSERT_FALSE(object[1][0].isRoot());
 	ASSERT_TRUE(object[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1][0].childrenCount()));
 	ASSERT_EQ("f", object[1][0].name());
 	ASSERT_TRUE(&object[1] == &object[1][0].parent());
 
 	// test e
 	ASSERT_FALSE(object[1][1].isRoot());
 	ASSERT_TRUE(object[1][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(object[1][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(object[1][1].childrenCount()));
 	ASSERT_EQ("e", object[1][1].name());
 	ASSERT_TRUE(&object[1] == &object[1][1].parent());
 }
@@ -538,12 +538,12 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_TRUE(root.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root.childrenCount()));
 
 	// test moved
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_TRUE(moved.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("root", moved.name());
 }
 
@@ -562,7 +562,7 @@
 
 	Object moved(std::move(root));
 	ASSERT_TRUE(moved.isRoot());
-	ASSERT_EQ(2, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("a", moved[0].name());
 	ASSERT_EQ("b", moved[1].name());
 	ASSERT_EQ("root", moved[0].parent().name());
@@ -596,13 +596,13 @@
 
 	// test root
 	ASSERT_TRUE(moved.isRoot());
-	ASSERT_EQ(2, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(moved.childrenCount()));
 
 	// test a, b
 	ASSERT_EQ("a", moved[0].name());
 	ASSERT_EQ("b", moved[1].name());
-	ASSERT_EQ(2, static_cast<int>(moved[0].countChildren()));
-	ASSERT_EQ(2, static_cast<int>(moved[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(moved[0].childrenCount()));
+	ASSERT_EQ(2, static_cast<int>(moved[1].childrenCount()));
 	ASSERT_EQ("root", moved[0].parent().name());
 	ASSERT_EQ("root", moved[1].parent().name());
 	ASSERT_TRUE(&moved == &moved[0].parent());
@@ -645,13 +645,13 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_TRUE(root.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test copy
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_TRUE(moved.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("root", moved.name());
 }
 
@@ -760,26 +760,26 @@
 
 	// test root
 	ASSERT_TRUE(root.isRoot());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_TRUE(root[0].isLeaf());
 	ASSERT_FALSE(root[0].isRoot());
 	ASSERT_EQ("a", root[0].name());
-	ASSERT_EQ(0, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0].childrenCount()));
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test b
 	ASSERT_TRUE(root[1].isLeaf());
 	ASSERT_FALSE(root[1].isRoot());
-	ASSERT_EQ(0, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1].childrenCount()));
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test moved b
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_TRUE(moved.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("b", moved.name());
 }
 
@@ -811,60 +811,60 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_FALSE(root[0].isRoot());
 	ASSERT_FALSE(root[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[0].childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test c
 	ASSERT_FALSE(root[0][0].isRoot());
 	ASSERT_TRUE(root[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][0].childrenCount()));
 	ASSERT_EQ("c", root[0][0].name());
 	ASSERT_TRUE(&root[0] == &root[0][0].parent());
 
 	// test d
 	ASSERT_FALSE(root[0][1].isRoot());
 	ASSERT_TRUE(root[0][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][1].childrenCount()));
 	ASSERT_EQ("d", root[0][1].name());
 	ASSERT_TRUE(&root[0] == &root[0][1].parent());
 
 	// test b
 	ASSERT_FALSE(root[1].isRoot());
 	ASSERT_TRUE(root[1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1].childrenCount()));
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test moved b
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_FALSE(moved.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("b", moved.name());
 
 	// test moved b-e
 	ASSERT_FALSE(moved[0].isRoot());
 	ASSERT_TRUE(moved[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved[0].childrenCount()));
 	ASSERT_EQ("e", moved[0].name());
 	ASSERT_TRUE(&moved == &moved[0].parent());
 
 	// test moved b-f
 	ASSERT_FALSE(moved[1].isRoot());
 	ASSERT_FALSE(moved[1].isLeaf());
-	ASSERT_EQ(1, static_cast<int>(moved[1].countChildren()));
+	ASSERT_EQ(1, static_cast<int>(moved[1].childrenCount()));
 	ASSERT_EQ("f", moved[1].name());
 	ASSERT_TRUE(&moved == &moved[1].parent());
 
 	// test moved b-g
 	ASSERT_FALSE(moved[1][0].isRoot());
 	ASSERT_TRUE(moved[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved[1][0].childrenCount()));
 	ASSERT_EQ("g", moved[1][0].name());
 	ASSERT_TRUE(&moved[1] == &moved[1][0].parent());
 }
@@ -890,27 +890,27 @@
 
 	// test root
 	ASSERT_TRUE(root.isRoot());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_TRUE(root[0].isLeaf());
 	ASSERT_FALSE(root[0].isRoot());
-	ASSERT_EQ(0, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0].childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test b
 	ASSERT_TRUE(root[1].isLeaf());
 	ASSERT_FALSE(root[1].isRoot());
-	ASSERT_EQ(0, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1].childrenCount()));
 	ASSERT_EQ("b", root[1].name());
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test copied b
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_TRUE(copy.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("b", copy.name());
 }
 
@@ -942,81 +942,81 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_FALSE(root[0].isRoot());
 	ASSERT_FALSE(root[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[0].childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test c
 	ASSERT_FALSE(root[0][0].isRoot());
 	ASSERT_TRUE(root[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][0].childrenCount()));
 	ASSERT_EQ("c", root[0][0].name());
 	ASSERT_TRUE(&root[0] == &root[0][0].parent());
 
 	// test d
 	ASSERT_FALSE(root[0][1].isRoot());
 	ASSERT_TRUE(root[0][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][1].childrenCount()));
 	ASSERT_EQ("d", root[0][1].name());
 	ASSERT_TRUE(&root[0] == &root[0][1].parent());
 
 	// test b
 	ASSERT_FALSE(root[1].isRoot());
 	ASSERT_FALSE(root[1].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[1].childrenCount()));
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test e
 	ASSERT_FALSE(root[1][0].isRoot());
 	ASSERT_TRUE(root[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][0].childrenCount()));
 	ASSERT_EQ("e", root[1][0].name());
 	ASSERT_TRUE(&root[1] == &root[1][0].parent());
 
 	// test f
 	ASSERT_FALSE(root[1][1].isRoot());
 	ASSERT_FALSE(root[1][1].isLeaf());
-	ASSERT_EQ(1, static_cast<int>(root[1][1].countChildren()));
+	ASSERT_EQ(1, static_cast<int>(root[1][1].childrenCount()));
 	ASSERT_EQ("f", root[1][1].name());
 	ASSERT_TRUE(&root[1] == &root[1][1].parent());
 
 	// test g
 	ASSERT_FALSE(root[1][1][0].isRoot());
 	ASSERT_TRUE(root[1][1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][1][0].childrenCount()));
 	ASSERT_EQ("g", root[1][1][0].name());
 	ASSERT_TRUE(&root[1][1] == &root[1][1][0].parent());
 
 	// test copied b
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_FALSE(copy.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("b", copy.name());
 
 	// test copied b-e
 	ASSERT_FALSE(copy[0].isRoot());
 	ASSERT_TRUE(copy[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy[0].childrenCount()));
 	ASSERT_EQ("e", copy[0].name());
 	ASSERT_TRUE(&copy == &copy[0].parent());
 
 	// test copied b-f
 	ASSERT_FALSE(copy[1].isRoot());
 	ASSERT_FALSE(copy[1].isLeaf());
-	ASSERT_EQ(1, static_cast<int>(copy[1].countChildren()));
+	ASSERT_EQ(1, static_cast<int>(copy[1].childrenCount()));
 	ASSERT_EQ("f", copy[1].name());
 	ASSERT_TRUE(&copy == &copy[1].parent());
 
 	// test copied b-g
 	ASSERT_FALSE(copy[1][0].isRoot());
 	ASSERT_TRUE(copy[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy[1][0].childrenCount()));
 	ASSERT_EQ("g", copy[1][0].name());
 	ASSERT_TRUE(&copy[1] == &copy[1][0].parent());
 }
@@ -1038,12 +1038,12 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_TRUE(root.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root.childrenCount()));
 
 	// test moved
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_TRUE(moved.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved.childrenCount()));
 	ASSERT_EQ("root", moved.name());
 }
 
@@ -1080,48 +1080,48 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_FALSE(root[0].isRoot());
 	ASSERT_FALSE(root[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[0].childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test c
 	ASSERT_FALSE(root[0][0].isRoot());
 	ASSERT_TRUE(root[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][0].childrenCount()));
 	ASSERT_EQ("c", root[0][0].name());
 	ASSERT_TRUE(&root[0] == &root[0][0].parent());
 
 	// test copied x to b
 	ASSERT_FALSE(root[1].isRoot());
 	ASSERT_FALSE(root[1].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[1].childrenCount()));
 	ASSERT_EQ("x", root[1].name());
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test y
 	ASSERT_FALSE(root[1][0].isRoot());
 	ASSERT_TRUE(root[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][0].childrenCount()));
 	ASSERT_EQ("y", root[1][0].name());
 	ASSERT_TRUE(&root[1] == &root[1][0].parent());
 
 	// test z
 	ASSERT_FALSE(root[1][1].isRoot());
 	ASSERT_TRUE(root[1][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][1].childrenCount()));
 	ASSERT_EQ("z", root[1][1].name());
 	ASSERT_TRUE(&root[1] == &root[1][1].parent());
 
 	// test moved
 	ASSERT_TRUE(moved.isRoot());
 	ASSERT_TRUE(moved.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(moved.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(moved.childrenCount()));
 }
 
 /* --------------------------------------------------------
@@ -1141,13 +1141,13 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_TRUE(root.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test copied
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_TRUE(copy.isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("root", copy.name());
 }
 
@@ -1184,66 +1184,132 @@
 	// test root
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("root", root.name());
 
 	// test a
 	ASSERT_FALSE(root[0].isRoot());
 	ASSERT_FALSE(root[0].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[0].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[0].childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_TRUE(&root == &root[0].parent());
 
 	// test c
 	ASSERT_FALSE(root[0][0].isRoot());
 	ASSERT_TRUE(root[0][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[0][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[0][0].childrenCount()));
 	ASSERT_EQ("c", root[0][0].name());
 	ASSERT_TRUE(&root[0] == &root[0][0].parent());
 
 	// test copied x to b
 	ASSERT_FALSE(root[1].isRoot());
 	ASSERT_FALSE(root[1].isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root[1].countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root[1].childrenCount()));
 	ASSERT_EQ("x", root[1].name());
 	ASSERT_TRUE(&root == &root[1].parent());
 
 	// test y
 	ASSERT_FALSE(root[1][0].isRoot());
 	ASSERT_TRUE(root[1][0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][0].childrenCount()));
 	ASSERT_EQ("y", root[1][0].name());
 	ASSERT_TRUE(&root[1] == &root[1][0].parent());
 
 	// test z
 	ASSERT_FALSE(root[1][1].isRoot());
 	ASSERT_TRUE(root[1][1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(root[1][1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root[1][1].childrenCount()));
 	ASSERT_EQ("z", root[1][1].name());
 	ASSERT_TRUE(&root[1] == &root[1][1].parent());
 
 	// test original x
 	ASSERT_TRUE(copy.isRoot());
 	ASSERT_FALSE(copy.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(copy.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(copy.childrenCount()));
 	ASSERT_EQ("x", copy.name());
 
 	// test original y
 	ASSERT_FALSE(copy[0].isRoot());
 	ASSERT_TRUE(copy[0].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy[0].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy[0].childrenCount()));
 	ASSERT_EQ("y", copy[0].name());
 	ASSERT_TRUE(&copy == &copy[0].parent());
 
 	// test original z
 	ASSERT_FALSE(copy[1].isRoot());
 	ASSERT_TRUE(copy[1].isLeaf());
-	ASSERT_EQ(0, static_cast<int>(copy[1].countChildren()));
+	ASSERT_EQ(0, static_cast<int>(copy[1].childrenCount()));
 	ASSERT_EQ("z", copy[1].name());
 	ASSERT_TRUE(&copy == &copy[1].parent());
 }
 
 /* --------------------------------------------------------
+ * Item insertions
+ * -------------------------------------------------------- */
+
+TEST(ItemInsert, push)
+{
+	Object root("root");
+
+	root.pushItem(std::make_unique<TreeNodeItemProxy<Object>>("a"));
+	root.pushItem(std::make_unique<TreeNodeItemProxy<Object>>("b"));
+
+	ASSERT_EQ(2U, root.childrenCount());
+	ASSERT_EQ("b", root[0].name());
+	ASSERT_EQ("a", root[1].name());
+}
+
+TEST(ItemInsert, append)
+{
+	Object root("root");
+
+	root.appendItem(std::make_unique<TreeNodeItemProxy<Object>>("a"));
+	root.appendItem(std::make_unique<TreeNodeItemProxy<Object>>("b"));
+
+	ASSERT_EQ(2U, root.childrenCount());
+	ASSERT_EQ("a", root[0].name());
+	ASSERT_EQ("b", root[1].name());
+}
+
+/* --------------------------------------------------------
+ * Item inspection
+ * -------------------------------------------------------- */
+
+TEST(ItemInspection, ref)
+{
+	Object root("root");
+
+	root.append(Object("a"));
+	root.append(Object("b"));
+	root.append(Object("c"));
+
+	// We only ref it, so it must be kept
+	std::unique_ptr<TreeNodeItem<Object>> &item = root.itemAt(0);
+	ASSERT_EQ("a", item->value().name());
+
+	// It should be empty
+	std::unique_ptr<TreeNodeItem<Object>> &item2 = root.itemAt(0);
+	ASSERT_EQ("a", item2->value().name());
+}
+
+TEST(ItemInspection, take)
+{
+	Object root("root");
+
+	root.append(Object("a"));
+	root.append(Object("b"));
+	root.append(Object("c"));
+
+	// We take the unique_ptr, it is moved
+	std::unique_ptr<TreeNodeItem<Object>> item = std::move(root.itemAt(0));
+	ASSERT_EQ("a", item->value().name());
+
+	// It should be empty
+	std::unique_ptr<TreeNodeItem<Object>> &item2 = root.itemAt(0);
+	ASSERT_TRUE(item2 == nullptr);
+}
+
+/* --------------------------------------------------------
  * Remove functions
  * -------------------------------------------------------- */
 
@@ -1256,7 +1322,7 @@
 	root.append(Object("c"));
 	root.clear();
 
-	ASSERT_EQ(0, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(0, static_cast<int>(root.childrenCount()));
 }
 
 TEST(Remove, index)
@@ -1268,7 +1334,7 @@
 	root.append(Object("c"));
 	root.remove(2);
 
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_EQ("b", root[1].name());
 }
@@ -1282,7 +1348,7 @@
 	root.append(Object("c"));
 	root.remove(root[2]);
 
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_EQ("b", root[1].name());
 }
@@ -1296,7 +1362,7 @@
 	root.append(Object("c"));
 	root.removeSame(Object("c"));
 
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_EQ("b", root[1].name());
 }
@@ -1361,7 +1427,7 @@
 
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("b", root[0].name());
 	ASSERT_EQ("a", root[1].name());
 }
@@ -1375,7 +1441,7 @@
 
 	ASSERT_TRUE(root.isRoot());
 	ASSERT_FALSE(root.isLeaf());
-	ASSERT_EQ(2, static_cast<int>(root.countChildren()));
+	ASSERT_EQ(2, static_cast<int>(root.childrenCount()));
 	ASSERT_EQ("a", root[0].name());
 	ASSERT_EQ("b", root[1].name());
 }
@@ -1510,8 +1576,8 @@
 		FAIL() << ex.what();
 	}
 
-	ASSERT_EQ(0U, root[1].countChildren());
-	ASSERT_EQ(1U, root[0].countChildren());
+	ASSERT_EQ(0U, root[1].childrenCount());
+	ASSERT_EQ(1U, root[0].childrenCount());
 	ASSERT_EQ("d", root[0][0].name());
 	ASSERT_TRUE(&root[0][0].parent() == &root[0]);
 }