From 0922764e54d6cba4d0e4524d9c2abb4bc6c886fa Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 6 Sep 2016 14:22:28 +0200
Subject: [PATCH] add forward_tree

---
 alib2std/src/extensions/forward_tree.hpp      | 743 ++++++++++++++++++
 alib2std/src/extensions/tree.hpp              | 472 +----------
 alib2std/src/extensions/tree_base.hpp         | 481 ++++++++++++
 alib2std/src/tree                             |   3 +
 .../test-src/extensions/ForwardTreeTest.cpp   | 143 ++++
 .../test-src/extensions/ForwardTreeTest.h     |  38 +
 alib2std/test-src/extensions/TreeBaseTest.cpp |  42 +
 alib2std/test-src/extensions/TreeBaseTest.h   | 105 +++
 alib2std/test-src/extensions/TreeTest.cpp     |  50 +-
 alib2std/test-src/extensions/TreeTest.h       |  91 +--
 10 files changed, 1569 insertions(+), 599 deletions(-)
 create mode 100644 alib2std/src/extensions/forward_tree.hpp
 create mode 100644 alib2std/src/extensions/tree_base.hpp
 create mode 100644 alib2std/test-src/extensions/ForwardTreeTest.cpp
 create mode 100644 alib2std/test-src/extensions/ForwardTreeTest.h
 create mode 100644 alib2std/test-src/extensions/TreeBaseTest.cpp
 create mode 100644 alib2std/test-src/extensions/TreeBaseTest.h

diff --git a/alib2std/src/extensions/forward_tree.hpp b/alib2std/src/extensions/forward_tree.hpp
new file mode 100644
index 0000000000..0a7dabf536
--- /dev/null
+++ b/alib2std/src/extensions/forward_tree.hpp
@@ -0,0 +1,743 @@
+/*
+ * forward_tree.hpp
+ *
+ * Created on: Jul 2, 2016
+ * Author: Jan Travnicek
+ */
+
+#ifndef __FORWARD_TREE_HPP_
+#define __FORWARD_TREE_HPP_
+
+namespace std {
+
+/*template < class T >
+struct AnyArity {
+	bool operator ()( const T &, unsigned ) const {
+		return true;
+	}
+
+};*/
+
+template < class T, class ArityChecker = AnyArity < T > >
+class forward_tree {
+
+	ArityChecker arityChecker;
+
+	struct tree_node {
+		T data;
+
+		std::vector < tree_node > children;
+
+		tree_node ( const T & data, const std::vector < tree_node > & children ) : data ( data ), children ( children ) {
+		}
+
+		tree_node ( T && data, std::vector < tree_node > && children ) : data ( std::move ( data ) ), children ( std::move ( children ) ) {
+		}
+
+		~tree_node ( ) noexcept {
+		}
+
+		tree_node ( const tree_node & node ) : data ( node.data ), children ( node.children ) {
+		}
+
+		tree_node ( tree_node && node ) noexcept : data ( std::move ( node.data ) ), children ( std::move ( node.children ) ) {
+		}
+
+		tree_node & operator =( const tree_node & node ) {
+			return this->operator =( tree_node ( node ) );
+		}
+
+		tree_node & operator =( tree_node && node ) noexcept {
+			data = std::move ( node.data );
+			children = std::move ( node.children );
+
+			return * this;
+		}
+
+		T & getData ( ) {
+			return data;
+		}
+
+		const T & getData ( ) const {
+			return data;
+		}
+
+		std::vector < tree_node > & getChildren ( ) {
+			return children;
+		}
+
+		const std::vector < tree_node > & getChildren ( ) const {
+			return children;
+		}
+
+	};
+
+	tree_node root;
+
+	std::vector < tree_node > fromTree ( const std::vector < forward_tree < T, ArityChecker > > & input ) {
+		std::vector < tree_node > res;
+
+		for ( const forward_tree < T, ArityChecker > & subtree : input )
+			res.push_back ( subtree.root );
+
+		return res;
+	}
+
+public:
+	class const_children_iterator : public std::iterator < std::bidirectional_iterator_tag, T > {
+		typename std::vector < tree_node >::const_iterator node;
+
+	public:
+		const_children_iterator ( typename std::vector < tree_node >::const_iterator node ) : node ( node ) {
+		}
+
+		const_children_iterator ( const const_children_iterator & other ) : node ( other.node ) {
+		}
+
+		const_children_iterator & operator ++( ) {
+			++node;
+			return * this;
+		}
+
+		const_children_iterator operator ++( int ) {
+			const_children_iterator tmp ( * this );
+
+			operator ++( );
+			return tmp;
+		}
+
+		const_children_iterator & operator --( ) {
+			--node;
+			return * this;
+		}
+
+		const_children_iterator operator --( int ) {
+			const_children_iterator tmp ( * this );
+
+			operator --( );
+			return tmp;
+		}
+
+		bool operator ==( const const_children_iterator & other ) {
+			return node == other.node;
+		}
+
+		bool operator !=( const const_children_iterator & other ) {
+			return !( * this == other );
+		}
+
+		const T & operator *( ) const {
+			return node->getData ( );
+		}
+
+		size_t operator -( const const_children_iterator other ) const {
+			return node - other.node;
+		}
+
+		const_children_iterator begin ( ) const {
+			return node->getChildren ( ).begin ( );
+		}
+
+		const_children_iterator end ( ) const {
+			return node->getChildren ( ).end ( );
+		}
+
+	private:
+		const tree_node & getTreeNode ( ) const {
+			return * node;
+		}
+
+		typename std::vector < tree_node >::const_iterator getUnderlyingIterator ( ) const {
+			return node;
+		}
+
+		template < class F, class G >
+		friend class forward_tree;
+	};
+
+	class const_structure_iterator : public std::iterator < std::bidirectional_iterator_tag, T > {
+		typename std::vector < tree_node >::const_iterator node;
+		typename std::deque < const tree_node * > parents;
+		unsigned level;
+
+		bool virtual_node;
+		bool isEnd;
+
+	public:
+		const_structure_iterator ( typename std::vector < tree_node >::const_iterator node ) : node ( node ), parents ( ), level ( 0 ), virtual_node ( false ), isEnd ( false ) {
+		}
+
+		const_structure_iterator ( const const_structure_iterator & other ) : node ( other.node ), parents ( other.parents ), level ( other.level ), virtual_node ( other.virtual_node ) {
+		}
+
+		const_structure_iterator & operator ++( ) {
+			if ( virtual_node ) {
+				if ( parents.size ( ) ) {
+					++node;
+
+					const tree_node * parent = parents.back ( );
+
+					if ( node == parent->getChildren ( ).end ( ) ) {
+						--level;
+						node = typename std::vector < tree_node >::const_iterator ( parent );
+					} else {
+						virtual_node = false;
+					}
+				} else {
+					++node;
+					virtual_node = false;
+					isEnd = true;
+				}
+			} else {
+				typename std::vector < tree_node >::const_iterator newIter = node->getChildren ( ).begin ( );
+
+				if ( newIter != node->getChildren ( ).end ( ) ) {
+					++level;
+					node = newIter;
+
+					parents.push_back ( & * node );
+				} else {
+					virtual_node = true;
+				}
+			}
+
+			return * this;
+		}
+
+		const_structure_iterator operator ++( int ) {
+			const_structure_iterator tmp ( * this );
+
+			operator ++( );
+			return tmp;
+		}
+
+		const_structure_iterator & operator --( ) {
+			if ( isEnd ) {
+				--node;
+				virtual_node = true;
+				isEnd = false;
+			} else if ( virtual_node ) {
+				typename std::vector < tree_node >::const_iterator newIter = node->getChildren ( ).end ( );
+
+				if ( newIter != node->getChildren ( ).begin ( ) ) {
+					++level;
+					node = newIter;
+					--node;
+
+					parents.push_back ( & * node );
+				} else {
+					virtual_node = false;
+				}
+			} else {
+				if ( parents.size ( ) ) {
+					const tree_node * parent = parents.back ( );
+
+					if ( node == parent->getChildren ( ).begin ( ) ) {
+						--level;
+						node = typename std::vector < tree_node >::const_iterator ( parent );
+					} else {
+						--node;
+						virtual_node = true;
+					}
+				}
+			}
+
+			return * this;
+		}
+
+		const_structure_iterator operator --( int ) {
+			const_structure_iterator tmp ( * this );
+
+			operator --( );
+			return tmp;
+		}
+
+		bool operator ==( const const_structure_iterator & other ) {
+			return node == other.node && virtual_node == other.virtual_node;
+		}
+
+		bool operator !=( const const_structure_iterator & other ) {
+			return !( * this == other );
+		}
+
+		const T & operator *( ) const {
+			return node->getData ( );
+		}
+
+		unsigned getLevel ( ) const {
+			return level;
+		}
+
+		bool getVirtual ( ) const {
+			return virtual_node;
+		}
+
+	private:
+		const tree_node & getTreeNode ( ) const {
+			return * node;
+		}
+
+		typename std::vector < tree_node >::const_iterator getUnderlyingIterator ( ) const {
+			return node;
+		}
+
+		template < class F, class G >
+		friend class forward_tree;
+	};
+
+	class const_prefix_iterator : public std::iterator < std::bidirectional_iterator_tag, T > {
+		const_structure_iterator node;
+
+	public:
+		const_prefix_iterator ( typename std::vector < tree_node >::const_iterator node ) : node ( node ) {
+		}
+
+		const_prefix_iterator ( const const_prefix_iterator & other ) : node ( other.node ) {
+		}
+
+		const_prefix_iterator & operator ++( ) {
+			while ( ( ++node ).getVirtual ( ) );
+
+			return * this;
+		}
+
+		const_prefix_iterator operator ++( int ) {
+			const_prefix_iterator tmp ( * this );
+
+			operator ++( );
+			return tmp;
+		}
+
+		const_prefix_iterator & operator --( ) {
+			while ( ( --node ).getVirtual ( ) );
+
+			return * this;
+		}
+
+		const_prefix_iterator operator --( int ) {
+			const_prefix_iterator tmp ( * this );
+
+			operator --( );
+			return tmp;
+		}
+
+		bool operator ==( const const_prefix_iterator & other ) {
+			return node == other.node;
+		}
+
+		bool operator !=( const const_prefix_iterator & other ) {
+			return !( * this == other );
+		}
+
+		const T & operator *( ) const {
+			return * node;
+		}
+
+		unsigned getLevel ( ) const {
+			return node.getLevel ( );
+		}
+
+	private:
+		const tree_node & getTreeNode ( ) const {
+			return node.getTreeNode ( );
+		}
+
+		typename std::vector < tree_node >::const_iterator getUnderlyingIterator ( ) const {
+			return node.getUnderlyingIterator;
+		}
+
+		template < class F, class G >
+		friend class forward_tree;
+	};
+
+	class const_postfix_iterator : public std::iterator < std::bidirectional_iterator_tag, T > {
+		const_structure_iterator node;
+
+	public:
+		const_postfix_iterator ( typename std::vector < tree_node >::const_iterator node ) : node ( node ) {
+		}
+
+		const_postfix_iterator ( const const_postfix_iterator & other ) : node ( other.node ) {
+		}
+
+		const_postfix_iterator & operator ++( ) {
+			while ( !( ++node ).getVirtual ( ) && !node.isEnd );
+
+			return * this;
+		}
+
+		const_postfix_iterator operator ++( int ) {
+			const_postfix_iterator tmp ( * this );
+
+			operator ++( );
+			return tmp;
+		}
+
+		const_postfix_iterator & operator --( ) {
+			while ( !( --node ).getVirtual ( ) );
+
+			return * this;
+		}
+
+		const_postfix_iterator operator --( int ) {
+			const_postfix_iterator tmp ( * this );
+
+			operator --( );
+			return tmp;
+		}
+
+		bool operator ==( const const_postfix_iterator & other ) {
+			return node == other.node;
+		}
+
+		bool operator !=( const const_postfix_iterator & other ) {
+			return !( * this == other );
+		}
+
+		const T & operator *( ) const {
+			return * node;
+		}
+
+		unsigned getLevel ( ) const {
+			return node.getLevel ( );
+		}
+
+	private:
+		const tree_node & getTreeNode ( ) const {
+			return node.getTreeNode ( );
+		}
+
+		typename std::vector < tree_node >::const_iterator getUnderlyingIterator ( ) const {
+			return node.getUnderlyingIterator ( );
+		}
+
+		template < class F, class G >
+		friend class forward_tree;
+	};
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+private:
+	const_children_iterator insert_helper ( const_children_iterator under, const_children_iterator position, const_children_iterator begin, const_children_iterator end ) {
+		tree_node * under_node = const_cast < tree_node * > ( & under.getTreeNode ( ) );
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under_node->getChildren ( ) );
+
+		size_t insertedSize = end - begin;
+
+		if ( !arityChecker ( * under, children.size ( ) + insertedSize ) )
+			throw "Invalid number of children";
+
+		std::vector < tree_node > inserted;
+
+		for ( const_children_iterator beginCopy = begin; beginCopy != end; ++beginCopy )
+			inserted.push_back ( beginCopy.getTreeNode ( ) );
+
+		typename std::vector < tree_node >::iterator iter = children.insert ( position.getUnderlyingIterator ( ), inserted.begin ( ), inserted.end ( ) );
+		typename std::vector < tree_node >::const_iterator citer = iter;
+		return citer;
+	}
+
+public:
+	const_children_iterator insert ( const_children_iterator under, const_children_iterator position, const forward_tree < T, ArityChecker > & value ) {
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under.getTreeNode ( ).getChildren ( ) );
+
+		typename std::vector < tree_node >::iterator iter = children.insert ( position.getUnderlyingIterator ( ), value.root );
+		typename std::vector < tree_node >::const_iterator res = iter;
+		return res;
+	}
+
+	const_children_iterator insert ( const_children_iterator under, const_children_iterator position, forward_tree < T, ArityChecker > && value ) {
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under.getTreeNode ( ).getChildren ( ) );
+
+		typename std::vector < tree_node >::iterator iter = children.insert ( position.getUnderlyingIterator ( ), std::move ( value.root ) );
+		typename std::vector < tree_node >::const_iterator res = iter;
+		return res;
+	}
+
+	template < class Iterator >
+	const_children_iterator insert ( const_children_iterator under, const_children_iterator position, Iterator begin, Iterator end ) {
+		std::vector < tree_node > children;
+
+		for ( ; begin != end; ++begin )
+			children.push_back ( tree_node ( * begin, { } ) );
+
+		return insert_helper ( under, position, children.cbegin ( ), children.cend ( ) );
+	}
+
+	const_children_iterator insert ( const_children_iterator under, const_children_iterator position, const_children_iterator begin, const_children_iterator end ) {
+		return insert_helper ( under, position, begin, end );
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+public:
+	forward_tree ( const T & data, const std::vector < forward_tree < T, ArityChecker > > & subtrees, ArityChecker arityChecker = ArityChecker ( ) ) : arityChecker ( arityChecker ), root ( data, fromTree ( subtrees ) ) {
+		if ( !arityChecker ( data, subtrees.size ( ) ) )
+			throw "Invalid number of children";
+	}
+
+	template < typename ... Types >
+	forward_tree ( const T & data, Types ... subtrees, ArityChecker arityChecker ) : forward_tree ( data, std::vector < forward_tree < T, ArityChecker > > { subtrees ... }, arityChecker ) {
+	}
+
+	template < typename ... Types >
+	forward_tree ( const T & data, Types ... subtrees ) : forward_tree ( data, std::vector < forward_tree < T, ArityChecker > > { subtrees ... }, ArityChecker ( ) ) {
+	}
+
+	template < typename Iterator, typename std::enable_if < std::is_iterator < Iterator >::value >::type >
+	forward_tree ( const T & data, Iterator begin, Iterator end ) : root ( data, { } ) {
+		std::vector < tree_node > children;
+
+		for ( ; begin != end; ++begin )
+			children.push_back ( tree_node ( * begin, { } ) );
+
+		insert_helper ( begin ( ), begin ( ).end ( ), children.cbegin ( ), children.cend ( ) );
+	}
+
+	forward_tree ( const T & data, const_children_iterator begin, const_children_iterator end ) : root ( data, { } ) {
+		insert_helper ( begin ( ), begin ( ).end ( ), begin, end );
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	const_children_iterator begin ( ) const {
+		return typename std::vector < tree_node >::const_iterator ( & root );
+	}
+
+	const_children_iterator end ( ) const {
+		return typename std::vector < tree_node >::const_iterator ( & root + 1 );
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	const_prefix_iterator prefix_begin ( ) const {
+		return typename std::vector < tree_node >::const_iterator ( & root );
+	}
+
+	const_prefix_iterator prefix_end ( ) const {
+		const_prefix_iterator res ( typename std::vector < tree_node >::const_iterator ( & root + 1 ) );
+
+		res.node.isEnd = true;
+		return res;
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	const_postfix_iterator postfix_begin ( ) const {
+		const_postfix_iterator res { typename std::vector < tree_node >::const_iterator ( & root ) };
+
+		while ( !( res.node ).getVirtual ( ) ) ++res.node;
+
+		return res;
+	}
+
+	const_postfix_iterator postfix_end ( ) const {
+		const_postfix_iterator res ( typename std::vector < tree_node >::const_iterator ( & root + 1 ) );
+
+		res.node.isEnd = true;
+		return res;
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	const_structure_iterator structure_begin ( ) const {
+		return typename std::vector < tree_node >::const_iterator ( & root );
+	}
+
+	const_structure_iterator structure_end ( ) const {
+		const_structure_iterator res ( typename std::vector < tree_node >::const_iterator ( & root + 1 ) );
+
+		res.isEnd = true;
+		return res;
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	void push_back ( const_children_iterator under, const T & value ) {
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under.getTreeNode ( ).getChildren ( ) );
+
+		if ( !arityChecker ( * under, children.size ( ) + 1 ) )
+			throw "Invalid number of children";
+
+		children.push_back ( tree_node ( value, { } ) );
+	}
+
+	void push_back ( const_children_iterator under, T && value ) {
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under.getTreeNode ( ).getChildren ( ) );
+
+		if ( !arityChecker ( * under, children.size ( ) + 1 ) )
+			throw "Invalid number of children";
+
+		children.push_back ( tree_node ( std::move ( value ), { } ) );
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	const_children_iterator erase ( const_children_iterator under, const_children_iterator position ) {
+		std::vector < tree_node > & children = const_cast < std::vector < tree_node > & > ( under.getTreeNode ( ).getChildren ( ) );
+
+		if ( !arityChecker ( * under, children.size ( ) - 1 ) )
+			throw "Invalid number of children";
+
+		typename std::vector < tree_node >::iterator iter = children.erase ( position.getUnderlyingIterator ( ) );
+		typename std::vector < tree_node >::const_iterator res = iter;
+		return res;
+	}
+
+	// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	template < class ... Indexes >
+	const T & operator ()( Indexes ... indexes ) const {
+		const tree_node * node = & root;
+
+		( void ) std::initializer_list < int > { ( node = & node->getChildren ( )[indexes], 0 ) ... };
+
+		return node->getData ( );
+	}
+
+private:
+	class SubscriptAccess {
+		tree_node * node;
+		const ArityChecker & arityChecker;
+
+	public:
+		SubscriptAccess ( tree_node * node, const ArityChecker & arityChecker ) : node ( node ), arityChecker ( arityChecker ) {
+		}
+
+		SubscriptAccess ( const SubscriptAccess & ) = delete;
+		SubscriptAccess ( SubscriptAccess && ) = delete;
+
+		SubscriptAccess & operator =( const SubscriptAccess & ) = delete;
+		SubscriptAccess & operator =( SubscriptAccess && ) = delete;
+
+		operator const T &( ) {
+			return node->getData ( );
+		}
+
+		SubscriptAccess & operator =( const T & data ) {
+			if ( !arityChecker ( data, node->getChildren ( ).size ( ) ) )
+				throw "Invalid number of children";
+
+			node->getData ( ) = data;
+
+			return * this;
+		}
+
+		SubscriptAccess & operator =( const forward_tree < T, ArityChecker > & data ) {
+			* node = data.root;
+
+			return * this;
+		}
+
+		friend void swap ( SubscriptAccess && first, SubscriptAccess && second ) {
+			tree_node tmp = std::move ( * first.node );
+
+			* first.node = std::move ( * second.node );
+			* second.node = std::move ( tmp );
+		}
+
+	};
+
+public:
+	template < class ... Indexes >
+	SubscriptAccess operator ()( Indexes ... indexes ) {
+		tree_node * node = & root;
+
+		( void ) std::initializer_list < int > { ( node = & node->getChildren ( )[indexes], 0 ) ... };
+
+		return { node, arityChecker };
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+	friend void swap ( forward_tree & first, forward_tree & second ) {
+		swap ( std::move ( first ( ) ), std::move ( second ( ) ) );
+	}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+	int compare ( const forward_tree & other ) const {
+		std::compare < typename std::decay < T >::type > comp;
+		auto iterF = this->prefix_begin ( );
+		auto iterS = other.prefix_begin ( );
+
+		for ( ; iterF != this->prefix_end ( ) || iterS != other.prefix_end ( ); ++iterF, ++iterS ) {
+			int res = comp ( * iterF, * iterS );
+
+			if ( res != 0 ) return res;
+		}
+
+		if ( iterF != this->prefix_end ( ) ) return -1;
+
+		if ( iterS != other.prefix_end ( ) ) return 1;
+
+		return 0;
+	}
+
+	bool operator ==( const forward_tree & other ) {
+		return compare ( other ) == 0;
+	}
+
+	bool operator !=( const forward_tree & other ) {
+		return compare ( other ) != 0;
+	}
+
+	bool operator <( const forward_tree & other ) {
+		return compare ( other ) < 0;
+	}
+
+	bool operator <=( const forward_tree & other ) {
+		return compare ( other ) <= 0;
+	}
+
+	bool operator >( const forward_tree & other ) {
+		return compare ( other ) > 0;
+	}
+
+	bool operator >=( const forward_tree & other ) {
+		return compare ( other ) >= 0;
+	}
+
+};
+
+template < class T, class ... Ts >
+std::ostream & operator <<( std::ostream & out, const forward_tree < T, Ts ... > & t ) {
+	out << "[";
+
+	unsigned level = 0;
+
+	for ( typename forward_tree < T, Ts ... >::const_prefix_iterator iter = t.prefix_begin ( ); iter != t.prefix_end ( ); ) {
+		while ( iter.getLevel ( ) > level ) {
+			out << "[";
+			++level;
+		}
+
+		out << level << * iter;
+		++iter;
+
+		bool printComma = iter.getLevel ( ) == level;
+
+		while ( iter.getLevel ( ) < level ) {
+			out << "]";
+			--level;
+			printComma = true;
+		}
+
+		if ( printComma && ( level != 0 ) )
+			out << ",";
+	}
+
+	out << "]";
+	return out;
+}
+
+template < class T, class ... Ts >
+struct compare < forward_tree < T, Ts ... > > {
+	int operator ()( const forward_tree < T, Ts ... > & first, const forward_tree < T, Ts ... > & second ) const {
+		return first.compare ( second );
+	}
+
+};
+
+} /* namespace std */
+
+#endif /* __FORWARD_TREE_HPP_ */
diff --git a/alib2std/src/extensions/tree.hpp b/alib2std/src/extensions/tree.hpp
index f9b533c214..f94023e637 100644
--- a/alib2std/src/extensions/tree.hpp
+++ b/alib2std/src/extensions/tree.hpp
@@ -1,5 +1,5 @@
 /*
- * tree.hpp
+ * bidirectional_tree.hpp
  *
  * Created on: Jul 2, 2016
  * Author: Jan Travnicek
@@ -611,7 +611,7 @@ public:
 		return res;
 	}
 
-	// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+	// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 	template < class ... Indexes >
 	const T & operator ()( Indexes ... indexes ) const {
@@ -780,474 +780,6 @@ struct compare < tree < T, Ts ... > > {
 
 };
 
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-template < class Data >
-class BaseNode {
-	Data * parent;
-
-	template < class D, class CD, class C >
-	friend class NullaryNode;
-	template < class D, class CD, class C >
-	friend class UnaryNode;
-	template < class D, class CD, class C >
-	friend class BinaryNode;
-	template < class D, class CD, class C >
-	friend class TernaryNode;
-	template < class D, int I, class CD, class C >
-	friend class AnyaryNode;
-	template < class D, class CD, class C >
-	friend class FixedaryNode;
-	template < class D, class CD, class C >
-	friend class VararyNode;
-
-	Data * operator ->( ) {
-		return static_cast < Data * > ( this );
-	}
-
-	const Data * operator ->( ) const {
-		return static_cast < Data * > ( this );
-	}
-
-public:
-	BaseNode ( ) : parent ( nullptr ) {
-	}
-
-	virtual ~BaseNode ( ) noexcept {
-	}
-
-	BaseNode ( const BaseNode & ) : parent ( nullptr ) {
-	}
-
-	BaseNode ( BaseNode && ) noexcept : parent ( nullptr ) {
-	}
-
-	BaseNode & operator =( const BaseNode & ) {
-		return * this;
-	}
-
-	BaseNode & operator =( BaseNode && ) noexcept {
-		return * this;
-	}
-
-	Data * getParent ( ) {
-		return parent;
-	}
-
-	const Data * getParent ( ) const {
-		return parent;
-	}
-
-};
-
-template < class Data, int arity, class ConstData = Data, class Cast = Data >
-class AnyaryNode {
-	typename TupleBuilder < Data, arity >::type children;
-
-	template < std::size_t ... Indices >
-	void setParent ( std::index_sequence < Indices ... > ) {
-		( void ) std::initializer_list < void * > { std::get < Indices > ( children )->parent = static_cast < Cast * > ( this ) ... };
-	}
-
-public:
-	AnyaryNode ( typename TupleBuilder < Data, arity >::type children ) : children ( std::move ( children ) ) {
-		setParent ( std::make_index_sequence < arity > ( ) );
-	}
-
-	virtual ~AnyaryNode ( ) noexcept {
-	}
-
-	AnyaryNode ( const AnyaryNode & other ) : AnyaryNode ( other.children ) {
-	}
-
-	AnyaryNode ( AnyaryNode && other ) noexcept : AnyaryNode ( std::move ( other.children ) ) {
-	}
-
-	AnyaryNode & operator =( const AnyaryNode & other ) {
-		return * this = AnyaryNode ( other );
-	}
-
-	AnyaryNode & operator =( AnyaryNode && other ) noexcept {
-		std::swap ( this->children, other.children );
-
-		setParent ( std::make_index_sequence < arity > ( ) );
-
-		return * this;
-	}
-
-	const typename TupleBuilder < Data, arity >::type & getElements ( ) {
-		return children;
-	}
-
-	const typename TupleBuilder < ConstData, arity >::type & getElements ( ) const {
-		return reinterpret_cast < const typename TupleBuilder < ConstData, arity >::type & > ( children );
-	}
-
-	template < int N >
-	const ConstData & getElement ( ) const {
-		return reinterpret_cast < const ConstData & > ( std::get < N > ( children ) );
-	}
-
-	template < int N >
-	Data & getElement ( ) {
-		return std::get < N > ( children );
-	}
-
-	void setElements ( typename TupleBuilder < Data, arity >::type children ) {
-		children = std::move ( children );
-		setParent ( std::make_index_sequence < arity > ( ) );
-	}
-
-	template < int N >
-	void setElement ( Data d ) {
-		std::get < N > ( children ) = std::move ( d );
-		std::get < N > ( children )->parent = static_cast < Cast * > ( this );
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class NullaryNode : public AnyaryNode < Data, 0, ConstData, Cast > {
-public:
-	NullaryNode ( ) : AnyaryNode < Data, 0, ConstData, Cast > ( std::tuple < > ( ) ) {
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class UnaryNode : public AnyaryNode < Data, 1, ConstData, Cast > {
-public:
-	UnaryNode ( Data c ) : AnyaryNode < Data, 1, ConstData, Cast > ( std::make_tuple ( std::move ( c ) ) ) {
-	}
-
-	Data & getChild ( ) {
-		return this->template getElement < 0 > ( );
-	}
-
-	const ConstData & getChild ( ) const {
-		return this->template getElement < 0 > ( );
-	}
-
-	void setChild ( Data c ) {
-		this->template setElement < 0 > ( std::move ( c ) );
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class BinaryNode : public AnyaryNode < Data, 2, ConstData, Cast > {
-public:
-	BinaryNode ( Data l, Data r ) : AnyaryNode < Data, 2, ConstData, Cast > ( std::make_tuple ( std::move ( l ), std::move ( r ) ) ) {
-	}
-
-	Data & getLeft ( ) {
-		return this->template getElement < 0 > ( );
-	}
-
-	const ConstData & getLeft ( ) const {
-		return this->template getElement < 0 > ( );
-	}
-
-	void setLeft ( Data l ) {
-		this->template setElement < 0 > ( std::move ( l ) );
-	}
-
-	Data & getRight ( ) {
-		return this->template getElement < 1 > ( );
-	}
-
-	const ConstData & getRight ( ) const {
-		return this->template getElement < 1 > ( );
-	}
-
-	void setRight ( Data r ) {
-		this->template setElement < 1 > ( std::move ( r ) );
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class TernaryNode : public AnyaryNode < Data, 3, ConstData, Cast > {
-public:
-	TernaryNode ( Data f, Data s, Data t ) : AnyaryNode < Data, 3, ConstData, Cast > ( std::make_tuple ( std::move ( f ), std::move ( s ), std::move ( t ) ) ) {
-	}
-
-	Data & getFirst ( ) {
-		return this->template getElement < 0 > ( );
-	}
-
-	const ConstData & getFirst ( ) const {
-		return this->template getElement < 0 > ( );
-	}
-
-	void setFirst ( Data f ) {
-		this->template setElement < 0 > ( std::move ( f ) );
-	}
-
-	Data & getSecond ( ) {
-		return this->template getElement < 1 > ( );
-	}
-
-	const ConstData & getSecond ( ) const {
-		return this->template getElement < 1 > ( );
-	}
-
-	void setSecond ( Data s ) {
-		this->template setElement < 1 > ( std::move ( s ) );
-	}
-
-	Data & getThird ( ) {
-		return this->template getElement < 2 > ( );
-	}
-
-	const ConstData & getThird ( ) const {
-		return this->template getElement < 2 > ( );
-	}
-
-	void setThird ( Data t ) {
-		this->template setElement < 2 > ( std::move ( t ) );
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class FixedaryNode {
-	std::vector < Data > children;
-
-public:
-	template < typename ... Types >
-	FixedaryNode ( Types ... data ) {
-		Data args[] { std::move ( data ) ... };
-
-		for ( Data & child : args )
-			children.push_back ( std::move ( child ) );
-
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-	}
-
-	FixedaryNode ( std::vector < Data > c ) : children ( std::move ( c ) ) {
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-	}
-
-	virtual ~FixedaryNode ( ) noexcept {
-	}
-
-	FixedaryNode ( const FixedaryNode & other ) : FixedaryNode ( other.children ) {
-	}
-
-	FixedaryNode ( FixedaryNode && other ) noexcept : FixedaryNode ( std::move ( other.children ) ) {
-	}
-
-	FixedaryNode & operator =( const FixedaryNode & other ) {
-		return * this = FixedaryNode ( other );
-	}
-
-	FixedaryNode & operator =( FixedaryNode && other ) noexcept {
-		std::swap ( this->children, other.children );
-
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-
-		return * this;
-	}
-
-	std::vector < Data > & getChildren ( ) {
-		return children;
-	}
-
-	const std::vector < ConstData > & getChildren ( ) const {
-		return reinterpret_cast < const std::vector < ConstData > & > ( children );
-	}
-
-	void setChildren ( std::vector < Data > c ) {
-		if ( c.size ( ) != children.size ( ) )
-			throw "Arity != size";
-
-		children = std::move ( c );
-
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-	}
-
-	void setChild ( Data d, int index ) {
-		if ( children.size ( ) >= index )
-			throw "Index out of bounds";
-
-		children[index] = std::move ( d );
-
-		children[index]->parent = static_cast < Cast * > ( this );
-	}
-
-};
-
-template < class Data, class ConstData = Data, class Cast = Data >
-class VararyNode {
-	std::vector < Data > children;
-
-public:
-	VararyNode ( ) {
-	}
-
-	VararyNode ( std::vector < Data > c ) : children ( std::move ( c ) ) {
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-	}
-
-	virtual ~VararyNode ( ) noexcept {
-	}
-
-	VararyNode ( const VararyNode & other ) : VararyNode ( other.children ) {
-	}
-
-	VararyNode ( VararyNode && other ) noexcept : VararyNode ( std::move ( other.children ) ) {
-	}
-
-	VararyNode & operator =( const VararyNode & other ) {
-		return * this = VararyNode ( other );
-	}
-
-	VararyNode & operator =( VararyNode && other ) noexcept {
-		std::swap ( this->children, other.children );
-
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-
-		return * this;
-	}
-
-	std::vector < Data > & getChildren ( ) {
-		return children;
-	}
-
-	const std::vector < ConstData > & getChildren ( ) const {
-		return reinterpret_cast < const std::vector < ConstData > & > ( children );
-	}
-
-	void setChildren ( std::vector < Data > c ) {
-		children = std::move ( c );
-
-		for ( Data & child : children )
-			child->parent = static_cast < Cast * > ( this );
-	}
-
-	void setChild ( Data d, int index ) {
-		children[index] = std::move ( d );
-
-		children[index]->parent = static_cast < Cast * > ( this );
-	}
-
-	void setChild ( Data d, typename std::vector < Data >::iterator it ) {
-		* it = std::move ( d );
-
-		( * it )->parent = static_cast < Cast * > ( this );
-	}
-
-	typename std::vector < Data >::iterator insert ( typename std::vector < Data >::iterator it, Data d ) {
-		it = children.insert ( it, std::move ( d ) );
-
-		( * std::prev ( it ) )->parent = static_cast < Cast * > ( this );
-
-		return it;
-	}
-
-	template < class InputIterator >
-	typename std::vector < Data >::iterator insert ( typename std::vector < Data >::iterator it, InputIterator first, InputIterator last ) {
-		size_t off = it - children.begin ( );
-		size_t size = last - first;
-
-		children.insert ( it, first, last );
-		it = children.begin ( ) + off;
-
-		 // TODO on g++-4.9 use: it = children->insert( it, first, last );
-		typename std::vector < Data >::iterator end = it + size;
-
-		for ( ; it != end; it++ )
-			( * it )->parent = static_cast < Cast * > ( this );
-
-		return it;
-	}
-
-	void pushBackChild ( Data d ) {
-		children.push_back ( std::move ( d ) );
-		children[children.size ( ) - 1]->parent = static_cast < Cast * > ( this );
-	}
-
-};
-
-template < class Data, class ConstData, class Cast >
-class Tree {
-public:
-	static void setChild ( const UnaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < UnaryNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ) );
-	}
-
-	static void setLeft ( const BinaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < BinaryNode < Data, ConstData, Cast > & > ( node ).setLeft ( std::move ( child ) );
-	}
-
-	static void setRight ( const BinaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < BinaryNode < Data, ConstData, Cast > & > ( node ).setRight ( std::move ( child ) );
-	}
-
-	static void setFirst ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setFirst ( std::move ( child ) );
-	}
-
-	static void setSecond ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setSecond ( std::move ( child ) );
-	}
-
-	static void setThird ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setThird ( std::move ( child ) );
-	}
-
-	template < int arity >
-	static void setChildren ( const AnyaryNode < Data, arity, ConstData, Cast > & node, typename TupleBuilder < Data, arity >::type children ) {
-		const_cast < AnyaryNode < Data, arity, ConstData, Cast > & > ( node ).setChildren ( std::move ( children ) );
-	}
-
-	template < class N, int arity >
-	static void setChild ( const AnyaryNode < Data, arity, ConstData, Cast > & node, Data child ) {
-		const_cast < AnyaryNode < Data, arity, ConstData, Cast > & > ( node ).template setChild < N > ( std::move ( child ) );
-	}
-
-	static void setChildren ( const FixedaryNode < Data, ConstData, Cast > & node, std::vector < Data > child ) {
-		const_cast < FixedaryNode < Data, ConstData, Cast > & > ( node ).setChildren ( std::move ( child ) );
-	}
-
-	static void setChild ( const FixedaryNode < Data, ConstData, Cast > & node, Data child, int index ) {
-		const_cast < FixedaryNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), index );
-	}
-
-	static void setChildren ( const VararyNode < Data, ConstData, Cast > & node, std::vector < Data > children ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChildren ( std::move ( children ) );
-	}
-
-	static void setChild ( const VararyNode < Data, ConstData, Cast > & node, Data child, int index ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), index );
-	}
-
-	static void setChild ( const VararyNode < Data, ConstData, Cast > & node, Data child, typename std::vector < Data >::iterator it ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), it );
-	}
-
-	typename std::vector < Data >::iterator insert ( const VararyNode < Data, ConstData, Cast > & node, typename std::vector < Data >::iterator it, Data child ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).insert ( it, std::move ( child ) );
-	}
-
-	template < class InputIterator >
-	typename std::vector < Data >::iterator insert ( const VararyNode < Data, ConstData, Cast > & node, typename std::vector < Data >::iterator it, InputIterator first, InputIterator last ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).insert ( it, first, last );
-	}
-
-	static void pushBackChild ( const VararyNode < Data, ConstData, Cast > & node, Data child ) {
-		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).pushBackChild ( std::move ( child ) );
-	}
-
-};
-
 } /* namespace std */
 
 #endif /* __TREE_HPP_ */
diff --git a/alib2std/src/extensions/tree_base.hpp b/alib2std/src/extensions/tree_base.hpp
new file mode 100644
index 0000000000..031aadfc5f
--- /dev/null
+++ b/alib2std/src/extensions/tree_base.hpp
@@ -0,0 +1,481 @@
+/*
+ * tree.hpp
+ *
+ * Created on: Jul 2, 2016
+ * Author: Jan Travnicek
+ */
+
+#ifndef __TREE_BASE_HPP_
+#define __TREE_BASE_HPP_
+
+namespace std {
+
+template < class Data >
+class BaseNode {
+	Data * parent;
+
+	template < class D, class CD, class C >
+	friend class NullaryNode;
+	template < class D, class CD, class C >
+	friend class UnaryNode;
+	template < class D, class CD, class C >
+	friend class BinaryNode;
+	template < class D, class CD, class C >
+	friend class TernaryNode;
+	template < class D, int I, class CD, class C >
+	friend class AnyaryNode;
+	template < class D, class CD, class C >
+	friend class FixedaryNode;
+	template < class D, class CD, class C >
+	friend class VararyNode;
+
+	Data * operator ->( ) {
+		return static_cast < Data * > ( this );
+	}
+
+	const Data * operator ->( ) const {
+		return static_cast < Data * > ( this );
+	}
+
+public:
+	BaseNode ( ) : parent ( nullptr ) {
+	}
+
+	virtual ~BaseNode ( ) noexcept {
+	}
+
+	BaseNode ( const BaseNode & ) : parent ( nullptr ) {
+	}
+
+	BaseNode ( BaseNode && ) noexcept : parent ( nullptr ) {
+	}
+
+	BaseNode & operator =( const BaseNode & ) {
+		return * this;
+	}
+
+	BaseNode & operator =( BaseNode && ) noexcept {
+		return * this;
+	}
+
+	Data * getParent ( ) {
+		return parent;
+	}
+
+	const Data * getParent ( ) const {
+		return parent;
+	}
+
+};
+
+template < class Data, int arity, class ConstData = Data, class Cast = Data >
+class AnyaryNode {
+	typename TupleBuilder < Data, arity >::type children;
+
+	template < std::size_t ... Indices >
+	void setParent ( std::index_sequence < Indices ... > ) {
+		( void ) std::initializer_list < void * > { std::get < Indices > ( children )->parent = static_cast < Cast * > ( this ) ... };
+	}
+
+public:
+	AnyaryNode ( typename TupleBuilder < Data, arity >::type children ) : children ( std::move ( children ) ) {
+		setParent ( std::make_index_sequence < arity > ( ) );
+	}
+
+	virtual ~AnyaryNode ( ) noexcept {
+	}
+
+	AnyaryNode ( const AnyaryNode & other ) : AnyaryNode ( other.children ) {
+	}
+
+	AnyaryNode ( AnyaryNode && other ) noexcept : AnyaryNode ( std::move ( other.children ) ) {
+	}
+
+	AnyaryNode & operator =( const AnyaryNode & other ) {
+		return * this = AnyaryNode ( other );
+	}
+
+	AnyaryNode & operator =( AnyaryNode && other ) noexcept {
+		std::swap ( this->children, other.children );
+
+		setParent ( std::make_index_sequence < arity > ( ) );
+
+		return * this;
+	}
+
+	const typename TupleBuilder < Data, arity >::type & getElements ( ) {
+		return children;
+	}
+
+	const typename TupleBuilder < ConstData, arity >::type & getElements ( ) const {
+		return reinterpret_cast < const typename TupleBuilder < ConstData, arity >::type & > ( children );
+	}
+
+	template < int N >
+	const ConstData & getElement ( ) const {
+		return reinterpret_cast < const ConstData & > ( std::get < N > ( children ) );
+	}
+
+	template < int N >
+	Data & getElement ( ) {
+		return std::get < N > ( children );
+	}
+
+	void setElements ( typename TupleBuilder < Data, arity >::type children ) {
+		children = std::move ( children );
+		setParent ( std::make_index_sequence < arity > ( ) );
+	}
+
+	template < int N >
+	void setElement ( Data d ) {
+		std::get < N > ( children ) = std::move ( d );
+		std::get < N > ( children )->parent = static_cast < Cast * > ( this );
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class NullaryNode : public AnyaryNode < Data, 0, ConstData, Cast > {
+public:
+	NullaryNode ( ) : AnyaryNode < Data, 0, ConstData, Cast > ( std::tuple < > ( ) ) {
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class UnaryNode : public AnyaryNode < Data, 1, ConstData, Cast > {
+public:
+	UnaryNode ( Data c ) : AnyaryNode < Data, 1, ConstData, Cast > ( std::make_tuple ( std::move ( c ) ) ) {
+	}
+
+	Data & getChild ( ) {
+		return this->template getElement < 0 > ( );
+	}
+
+	const ConstData & getChild ( ) const {
+		return this->template getElement < 0 > ( );
+	}
+
+	void setChild ( Data c ) {
+		this->template setElement < 0 > ( std::move ( c ) );
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class BinaryNode : public AnyaryNode < Data, 2, ConstData, Cast > {
+public:
+	BinaryNode ( Data l, Data r ) : AnyaryNode < Data, 2, ConstData, Cast > ( std::make_tuple ( std::move ( l ), std::move ( r ) ) ) {
+	}
+
+	Data & getLeft ( ) {
+		return this->template getElement < 0 > ( );
+	}
+
+	const ConstData & getLeft ( ) const {
+		return this->template getElement < 0 > ( );
+	}
+
+	void setLeft ( Data l ) {
+		this->template setElement < 0 > ( std::move ( l ) );
+	}
+
+	Data & getRight ( ) {
+		return this->template getElement < 1 > ( );
+	}
+
+	const ConstData & getRight ( ) const {
+		return this->template getElement < 1 > ( );
+	}
+
+	void setRight ( Data r ) {
+		this->template setElement < 1 > ( std::move ( r ) );
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class TernaryNode : public AnyaryNode < Data, 3, ConstData, Cast > {
+public:
+	TernaryNode ( Data f, Data s, Data t ) : AnyaryNode < Data, 3, ConstData, Cast > ( std::make_tuple ( std::move ( f ), std::move ( s ), std::move ( t ) ) ) {
+	}
+
+	Data & getFirst ( ) {
+		return this->template getElement < 0 > ( );
+	}
+
+	const ConstData & getFirst ( ) const {
+		return this->template getElement < 0 > ( );
+	}
+
+	void setFirst ( Data f ) {
+		this->template setElement < 0 > ( std::move ( f ) );
+	}
+
+	Data & getSecond ( ) {
+		return this->template getElement < 1 > ( );
+	}
+
+	const ConstData & getSecond ( ) const {
+		return this->template getElement < 1 > ( );
+	}
+
+	void setSecond ( Data s ) {
+		this->template setElement < 1 > ( std::move ( s ) );
+	}
+
+	Data & getThird ( ) {
+		return this->template getElement < 2 > ( );
+	}
+
+	const ConstData & getThird ( ) const {
+		return this->template getElement < 2 > ( );
+	}
+
+	void setThird ( Data t ) {
+		this->template setElement < 2 > ( std::move ( t ) );
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class FixedaryNode {
+	std::vector < Data > children;
+
+public:
+	template < typename ... Types >
+	FixedaryNode ( Types ... data ) {
+		Data args[] { std::move ( data ) ... };
+
+		for ( Data & child : args )
+			children.push_back ( std::move ( child ) );
+
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+	}
+
+	FixedaryNode ( std::vector < Data > c ) : children ( std::move ( c ) ) {
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+	}
+
+	virtual ~FixedaryNode ( ) noexcept {
+	}
+
+	FixedaryNode ( const FixedaryNode & other ) : FixedaryNode ( other.children ) {
+	}
+
+	FixedaryNode ( FixedaryNode && other ) noexcept : FixedaryNode ( std::move ( other.children ) ) {
+	}
+
+	FixedaryNode & operator =( const FixedaryNode & other ) {
+		return * this = FixedaryNode ( other );
+	}
+
+	FixedaryNode & operator =( FixedaryNode && other ) noexcept {
+		std::swap ( this->children, other.children );
+
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+
+		return * this;
+	}
+
+	std::vector < Data > & getChildren ( ) {
+		return children;
+	}
+
+	const std::vector < ConstData > & getChildren ( ) const {
+		return reinterpret_cast < const std::vector < ConstData > & > ( children );
+	}
+
+	void setChildren ( std::vector < Data > c ) {
+		if ( c.size ( ) != children.size ( ) )
+			throw "Arity != size";
+
+		children = std::move ( c );
+
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+	}
+
+	void setChild ( Data d, int index ) {
+		if ( children.size ( ) >= index )
+			throw "Index out of bounds";
+
+		children[index] = std::move ( d );
+
+		children[index]->parent = static_cast < Cast * > ( this );
+	}
+
+};
+
+template < class Data, class ConstData = Data, class Cast = Data >
+class VararyNode {
+	std::vector < Data > children;
+
+public:
+	VararyNode ( ) {
+	}
+
+	VararyNode ( std::vector < Data > c ) : children ( std::move ( c ) ) {
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+	}
+
+	virtual ~VararyNode ( ) noexcept {
+	}
+
+	VararyNode ( const VararyNode & other ) : VararyNode ( other.children ) {
+	}
+
+	VararyNode ( VararyNode && other ) noexcept : VararyNode ( std::move ( other.children ) ) {
+	}
+
+	VararyNode & operator =( const VararyNode & other ) {
+		return * this = VararyNode ( other );
+	}
+
+	VararyNode & operator =( VararyNode && other ) noexcept {
+		std::swap ( this->children, other.children );
+
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+
+		return * this;
+	}
+
+	std::vector < Data > & getChildren ( ) {
+		return children;
+	}
+
+	const std::vector < ConstData > & getChildren ( ) const {
+		return reinterpret_cast < const std::vector < ConstData > & > ( children );
+	}
+
+	void setChildren ( std::vector < Data > c ) {
+		children = std::move ( c );
+
+		for ( Data & child : children )
+			child->parent = static_cast < Cast * > ( this );
+	}
+
+	void setChild ( Data d, int index ) {
+		children[index] = std::move ( d );
+
+		children[index]->parent = static_cast < Cast * > ( this );
+	}
+
+	void setChild ( Data d, typename std::vector < Data >::iterator it ) {
+		* it = std::move ( d );
+
+		( * it )->parent = static_cast < Cast * > ( this );
+	}
+
+	typename std::vector < Data >::iterator insert ( typename std::vector < Data >::iterator it, Data d ) {
+		it = children.insert ( it, std::move ( d ) );
+
+		( * std::prev ( it ) )->parent = static_cast < Cast * > ( this );
+
+		return it;
+	}
+
+	template < class InputIterator >
+	typename std::vector < Data >::iterator insert ( typename std::vector < Data >::iterator it, InputIterator first, InputIterator last ) {
+		size_t off = it - children.begin ( );
+		size_t size = last - first;
+
+		children.insert ( it, first, last );
+		it = children.begin ( ) + off;
+
+		 // TODO on g++-4.9 use: it = children->insert( it, first, last );
+		typename std::vector < Data >::iterator end = it + size;
+
+		for ( ; it != end; it++ )
+			( * it )->parent = static_cast < Cast * > ( this );
+
+		return it;
+	}
+
+	void pushBackChild ( Data d ) {
+		children.push_back ( std::move ( d ) );
+		children[children.size ( ) - 1]->parent = static_cast < Cast * > ( this );
+	}
+
+};
+
+template < class Data, class ConstData, class Cast >
+class Tree {
+public:
+	static void setChild ( const UnaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < UnaryNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ) );
+	}
+
+	static void setLeft ( const BinaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < BinaryNode < Data, ConstData, Cast > & > ( node ).setLeft ( std::move ( child ) );
+	}
+
+	static void setRight ( const BinaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < BinaryNode < Data, ConstData, Cast > & > ( node ).setRight ( std::move ( child ) );
+	}
+
+	static void setFirst ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setFirst ( std::move ( child ) );
+	}
+
+	static void setSecond ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setSecond ( std::move ( child ) );
+	}
+
+	static void setThird ( const TernaryNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < TernaryNode < Data, ConstData, Cast > & > ( node ).setThird ( std::move ( child ) );
+	}
+
+	template < int arity >
+	static void setChildren ( const AnyaryNode < Data, arity, ConstData, Cast > & node, typename TupleBuilder < Data, arity >::type children ) {
+		const_cast < AnyaryNode < Data, arity, ConstData, Cast > & > ( node ).setChildren ( std::move ( children ) );
+	}
+
+	template < class N, int arity >
+	static void setChild ( const AnyaryNode < Data, arity, ConstData, Cast > & node, Data child ) {
+		const_cast < AnyaryNode < Data, arity, ConstData, Cast > & > ( node ).template setChild < N > ( std::move ( child ) );
+	}
+
+	static void setChildren ( const FixedaryNode < Data, ConstData, Cast > & node, std::vector < Data > child ) {
+		const_cast < FixedaryNode < Data, ConstData, Cast > & > ( node ).setChildren ( std::move ( child ) );
+	}
+
+	static void setChild ( const FixedaryNode < Data, ConstData, Cast > & node, Data child, int index ) {
+		const_cast < FixedaryNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), index );
+	}
+
+	static void setChildren ( const VararyNode < Data, ConstData, Cast > & node, std::vector < Data > children ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChildren ( std::move ( children ) );
+	}
+
+	static void setChild ( const VararyNode < Data, ConstData, Cast > & node, Data child, int index ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), index );
+	}
+
+	static void setChild ( const VararyNode < Data, ConstData, Cast > & node, Data child, typename std::vector < Data >::iterator it ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).setChild ( std::move ( child ), it );
+	}
+
+	typename std::vector < Data >::iterator insert ( const VararyNode < Data, ConstData, Cast > & node, typename std::vector < Data >::iterator it, Data child ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).insert ( it, std::move ( child ) );
+	}
+
+	template < class InputIterator >
+	typename std::vector < Data >::iterator insert ( const VararyNode < Data, ConstData, Cast > & node, typename std::vector < Data >::iterator it, InputIterator first, InputIterator last ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).insert ( it, first, last );
+	}
+
+	static void pushBackChild ( const VararyNode < Data, ConstData, Cast > & node, Data child ) {
+		const_cast < VararyNode < Data, ConstData, Cast > & > ( node ).pushBackChild ( std::move ( child ) );
+	}
+
+};
+
+} /* namespace std */
+
+#endif /* __TREE_BASE_HPP_ */
diff --git a/alib2std/src/tree b/alib2std/src/tree
index 32683cb54c..bfe92c5dab 100644
--- a/alib2std/src/tree
+++ b/alib2std/src/tree
@@ -3,9 +3,12 @@
 
 #include <memory>
 #include <vector>
+#include <deque>
 #include <tuple>
 #include "iterator"
+#include "extensions/tree_base.hpp"
 #include "extensions/tree.hpp"
+#include "extensions/forward_tree.hpp"
 
 #endif /* __TREE_HEADER_WRAPPER */
 
diff --git a/alib2std/test-src/extensions/ForwardTreeTest.cpp b/alib2std/test-src/extensions/ForwardTreeTest.cpp
new file mode 100644
index 0000000000..445ddf2655
--- /dev/null
+++ b/alib2std/test-src/extensions/ForwardTreeTest.cpp
@@ -0,0 +1,143 @@
+#include "ForwardTreeTest.h"
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( ForwardTreeTest, "bits" );
+CPPUNIT_TEST_SUITE_REGISTRATION ( ForwardTreeTest );
+
+void ForwardTreeTest::setUp ( ) {
+}
+
+void ForwardTreeTest::tearDown ( ) {
+}
+
+void ForwardTreeTest::print_tree ( std::tree < char >::const_children_iterator biter, std::tree < char >::const_children_iterator eiter, std::string indent ) {
+	for ( std::tree < char >::const_children_iterator iter = biter; iter != eiter; iter++ ) {
+		std::cout << indent << * iter << std::endl;
+		print_tree ( iter.begin ( ), iter.end ( ), indent + " " );
+	}
+}
+
+void ForwardTreeTest::testTreeStdStructure ( ) {
+	std::tree < char > t ( 'a', std::tree < char > ( 'a' ), std::tree < char > ( 'b', std::tree < char > ( 'a' ), std::tree < char > ( 'b' ) ) );
+
+	// std::cout << "structure t " << std::boolalpha << t.checkStructure() << std::endl;
+
+	std::tree < char > t2 ( 'c' );
+
+	 // std::cout << "structure t2 " << std::boolalpha << t2.checkStructure() << std::endl;
+	t2.insert ( t2.begin ( ), t2.begin ( ).begin ( ), { 'c', std::tree < char > ( 'b' ) } );
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+
+	t2.insert ( t2.begin ( ), t2.begin ( ).end ( ), t.begin ( ), t.end ( ) );
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+
+	std::vector < char > data = { 'd', 'e' };
+	t2.insert ( t2.begin ( ), t2.begin ( ).end ( ), data.begin ( ), data.end ( ) );
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+
+	// print_tree ( t.begin(), t.end(), "");
+
+	t2.erase ( t2.begin ( ), std::prev ( t2.begin ( ).end ( ) ) );
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+	t2.push_back ( t2.begin ( ), 'f' );
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+
+	// print_tree ( t2.begin(), t2.end(), "");
+
+	CPPUNIT_ASSERT_EQUAL ( ( char ) t2 ( 1, 1 ), 'b' );
+	t2 ( 1, 1 ) = 'c';
+	CPPUNIT_ASSERT_EQUAL ( ( char ) t2 ( 1, 1 ), 'c' );
+
+	CPPUNIT_ASSERT ( t2.checkStructure ( ) );
+	std::tree < char >::const_prefix_iterator beg = t2.prefix_begin ( );
+	beg++;
+	beg++;
+	beg++;
+	beg++;
+	beg++;
+	beg++;
+	beg++;
+	beg--;
+	beg--;
+	beg--;
+	beg--;
+	beg--;
+	beg--;
+	beg--;
+
+	CPPUNIT_ASSERT ( beg == t2.prefix_begin ( ) );
+	std::cout << t2 << std::endl;
+	std::stringstream ss;
+	ss << t2;
+	CPPUNIT_ASSERT ( ss.str ( ) == "[0c[1c[2b],1a[2a,2c[3a,3b]],1d,1f]]" );
+
+	std::vector < std::pair < unsigned, char > > expectedPrefix = { { 0, 'c' }, { 1, 'c' }, { 2, 'b' }, { 1, 'a' }, { 2, 'a' }, { 2, 'c' }, { 3, 'a' }, { 3, 'b' }, { 1, 'd' }, { 1, 'f' } };
+	std::vector < std::pair < unsigned, char > >::const_iterator ref = expectedPrefix.begin ( );
+
+	for ( std::tree < char >::const_prefix_iterator iter = t2.prefix_begin ( ); iter != t2.prefix_end ( ); ++iter ) {
+		CPPUNIT_ASSERT ( iter.getLevel ( ) == ref->first );
+		CPPUNIT_ASSERT ( * iter == ref->second );
+		++iter;
+		--iter;
+		++ref;
+	}
+
+	std::vector < std::tuple < unsigned, char, bool > > expectedStructure = { std::make_tuple ( 0u, 'c', false ), std::make_tuple ( 1u, 'c', false ), std::make_tuple ( 2u, 'b', false ), std::make_tuple ( 2u, 'b', true ), std::make_tuple ( 1u, 'c', true ), std::make_tuple ( 1u, 'a', false ), std::make_tuple ( 2u, 'a', false ), std::make_tuple ( 2u, 'a', true ), std::make_tuple ( 2u, 'c', false ), std::make_tuple ( 3u, 'a', false ), std::make_tuple ( 3u, 'a', true ), std::make_tuple ( 3u, 'b', false ), std::make_tuple ( 3u, 'b', true ), std::make_tuple ( 2u, 'c', true ), std::make_tuple ( 1u, 'a', true ), std::make_tuple ( 1u, 'd', false ), std::make_tuple ( 1u, 'd', true ), std::make_tuple ( 1u, 'f', false ), std::make_tuple ( 1u, 'f', true ), std::make_tuple ( 0u, 'c', true ) };
+	std::vector < std::tuple < unsigned, char, bool > >::const_iterator ref2 = expectedStructure.begin ( );
+
+	for ( std::tree < char >::const_structure_iterator iter = t2.structure_begin ( ); iter != t2.structure_end ( ); ++iter ) {
+		CPPUNIT_ASSERT ( iter.getLevel ( ) == std::get < 0 > ( * ref2 ) );
+		CPPUNIT_ASSERT ( * iter == std::get < 1 > ( * ref2 ) );
+		CPPUNIT_ASSERT ( iter.getVirtual ( ) == std::get < 2 > ( * ref2 ) );
+		++iter;
+		--iter;
+		++ref2;
+	}
+
+	std::vector < std::pair < unsigned, char > > expectedPostfix = { { 2, 'b' }, { 1, 'c' }, { 2, 'a' }, { 3, 'a' }, { 3, 'b' }, { 2, 'c' }, { 1, 'a' }, { 1, 'd' }, { 1, 'f' }, { 0, 'c' } };
+	std::vector < std::pair < unsigned, char > >::const_iterator ref3 = expectedPostfix.begin ( );
+
+	for ( std::tree < char >::const_postfix_iterator iter = t2.postfix_begin ( ); iter != t2.postfix_end ( ); ++iter ) {
+		CPPUNIT_ASSERT ( iter.getLevel ( ) == ref3->first );
+		CPPUNIT_ASSERT ( * iter == ref3->second );
+		++iter;
+		--iter;
+		++ref3;
+	}
+
+	std::tree < char, RankedArityChecker > rt ( 'a', std::tree < char, RankedArityChecker > ( 'b', std::tree < char, RankedArityChecker > ( 'c' ) ), std::tree < char, RankedArityChecker > ( 'c' ) );
+
+	CPPUNIT_ASSERT_EQUAL ( ( char ) rt ( 0, 0 ), 'c' );
+	rt ( 0, 0 ) = 'd';
+	CPPUNIT_ASSERT_EQUAL ( ( char ) rt ( 0, 0 ), 'd' );
+	rt ( 0, 0 ) = std::tree < char, RankedArityChecker > ( 'e' );
+	CPPUNIT_ASSERT_EQUAL ( ( char ) rt ( 0, 0 ), 'e' );
+	CPPUNIT_ASSERT ( rt.checkStructure ( ) );
+
+	std::cout << rt << std::endl;
+	swap ( rt ( 0 ), rt ( 1 ) );
+	CPPUNIT_ASSERT ( rt.checkStructure ( ) );
+	std::cout << rt << std::endl;
+	std::stringstream ss2;
+	ss2 << rt;
+	CPPUNIT_ASSERT ( ss2.str ( ) == "[0a[1c,1b[2e]]]" );
+
+	std::tree < char, RankedArityChecker > rt2 ( 'c' );
+	swap ( rt, rt2 );
+
+	CPPUNIT_ASSERT ( rt.checkStructure ( ) );
+	std::cout << rt << std::endl;
+	std::stringstream ss3;
+	ss3 << rt;
+	CPPUNIT_ASSERT ( ss3.str ( ) == "[0c]" );
+	std::cout << rt2 << std::endl;
+
+	std::tree < char > cmp1 ( 'a' );
+	std::tree < char > cmp2 ( 'b' );
+	std::tree < char > cmp3 ( 'c' );
+
+	CPPUNIT_ASSERT ( cmp1 < cmp2 );
+	CPPUNIT_ASSERT ( cmp2 < cmp3 );
+	CPPUNIT_ASSERT ( cmp2 <= cmp3 );
+	CPPUNIT_ASSERT ( cmp2 == cmp2 );
+	CPPUNIT_ASSERT ( cmp1 != cmp2 );
+}
diff --git a/alib2std/test-src/extensions/ForwardTreeTest.h b/alib2std/test-src/extensions/ForwardTreeTest.h
new file mode 100644
index 0000000000..df89514116
--- /dev/null
+++ b/alib2std/test-src/extensions/ForwardTreeTest.h
@@ -0,0 +1,38 @@
+#ifndef TREE_TEST_H_
+#define TREE_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <compare>
+#include <tree>
+
+class ForwardTreeTest : public CppUnit::TestFixture {
+	CPPUNIT_TEST_SUITE ( ForwardTreeTest );
+	CPPUNIT_TEST ( testTreeStdStructure );
+	CPPUNIT_TEST_SUITE_END ( );
+
+public:
+
+	struct RankedArityChecker {
+		bool operator ()( char symbol, unsigned wantedRank ) const {
+			switch ( symbol ) {
+			case 'a':
+				return wantedRank == 2;
+
+			case 'b':
+				return wantedRank == 1;
+
+			default:
+				return wantedRank == 0;
+			}
+		}
+
+	};
+
+	void print_tree ( std::tree < char >::const_children_iterator biter, std::tree < char >::const_children_iterator eiter, std::string indent );
+	void setUp ( );
+	void tearDown ( );
+
+	void testTreeStdStructure();
+};
+
+#endif // TREE_TEST_H_
diff --git a/alib2std/test-src/extensions/TreeBaseTest.cpp b/alib2std/test-src/extensions/TreeBaseTest.cpp
new file mode 100644
index 0000000000..1c3e8c5299
--- /dev/null
+++ b/alib2std/test-src/extensions/TreeBaseTest.cpp
@@ -0,0 +1,42 @@
+#include "TreeBaseTest.h"
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( TreeBaseTest, "bits" );
+CPPUNIT_TEST_SUITE_REGISTRATION ( TreeBaseTest );
+
+void TreeBaseTest::setUp ( ) {
+}
+
+void TreeBaseTest::tearDown ( ) {
+}
+
+void TreeBaseTest::testRegexps ( ) {
+	RegExpIteration iter ( std::shared_ptr < RegExpElement > ( new RegExpEmpty ( ) ) );
+
+	CPPUNIT_ASSERT ( iter.getChild ( )->getParent ( ) == & iter );
+
+	RegExpIteration iter2 ( iter );
+	RegExpIteration iter3 ( iter2 );
+
+	CPPUNIT_ASSERT ( iter3.getChild ( )->getParent ( ) == & iter3 );
+
+	iter3 = iter;
+	RegExpIteration iter4 ( std::shared_ptr < RegExpElement > ( new RegExpEpsilon ( ) ) );
+	iter3 = iter4;
+
+	CPPUNIT_ASSERT ( iter3.getChild ( )->getParent ( ) == & iter3 );
+
+	RegExpSymbol s ( 'x' );
+	const RegExpSymbol & sr = s;
+	sr.getElements ( );
+}
+
+void TreeBaseTest::testRankedTree ( ) {
+	RankedTreeNode node ( 'a', 1, { RankedTreeNode ( 'b', 1, { RankedTreeNode ( 'c', 0, { } ) } ) } );
+	const RankedTreeNode & cnode = node;
+
+	for ( const RankedTreeNode & child : cnode.getChildren ( ) )
+		CPPUNIT_ASSERT ( child.getParent ( ) == & cnode );
+}
+
+void TreeBaseTest::testUnrankedTree ( ) {
+}
diff --git a/alib2std/test-src/extensions/TreeBaseTest.h b/alib2std/test-src/extensions/TreeBaseTest.h
new file mode 100644
index 0000000000..7c5adc4d10
--- /dev/null
+++ b/alib2std/test-src/extensions/TreeBaseTest.h
@@ -0,0 +1,105 @@
+#ifndef TREE_TEST_BASE_H_
+#define TREE_TEST_BASE_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <compare>
+#include <tree>
+
+class TreeBaseTest : public CppUnit::TestFixture {
+	CPPUNIT_TEST_SUITE ( TreeBaseTest );
+	CPPUNIT_TEST ( testRegexps );
+	CPPUNIT_TEST ( testRankedTree );
+	CPPUNIT_TEST ( testUnrankedTree );
+	CPPUNIT_TEST_SUITE_END ( );
+
+public:
+	class RegExpElement : public std::BaseNode < RegExpElement > {
+	};
+
+	class RegExpAlternation : public RegExpElement {
+	};
+
+	class RegExpConcatenation : public RegExpElement, public std::BinaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpConcatenation > {
+	public:
+		RegExpConcatenation ( std::shared_ptr < RegExpElement > left, std::shared_ptr < RegExpElement > right ) : BinaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpConcatenation > ( std::move ( left ), std::move ( right ) ) {
+		}
+
+	};
+
+	class RegExpIteration : public RegExpElement, public std::UnaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpIteration > {
+	public:
+		RegExpIteration ( std::shared_ptr < RegExpElement > element ) : UnaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpIteration > ( std::move ( element ) ) {
+		}
+
+	};
+
+	class RegExpSymbol : public RegExpElement, public std::NullaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpSymbol > {
+		char symbol;
+
+	public:
+		RegExpSymbol ( char symbol ) : symbol ( symbol ) {
+		}
+
+		char getSymbol ( ) const {
+			return symbol;
+		}
+
+	};
+
+	class RegExpEpsilon : public RegExpElement {
+	};
+
+	class RegExpEmpty : public RegExpElement {
+	};
+
+	class RegExp {
+		std::shared_ptr < RegExpElement > root;
+	};
+
+	class UnrankedTreeNode : public std::BaseNode < UnrankedTreeNode >, public std::VararyNode < UnrankedTreeNode > {
+		char symbol;
+
+	public:
+		UnrankedTreeNode ( char symbol, std::vector < UnrankedTreeNode > children ) : VararyNode < UnrankedTreeNode > ( std::move ( children ) ), symbol ( symbol ) {
+		}
+
+		char getSymbol ( ) const {
+			return symbol;
+		}
+
+	};
+
+	class UnrankedTree {
+		UnrankedTreeNode root;
+	};
+
+	class RankedTreeNode : public std::BaseNode < RankedTreeNode >, public std::FixedaryNode < RankedTreeNode > {
+		char symbol;
+		char arity;
+
+	public:
+		RankedTreeNode ( char symbol, unsigned arity, std::vector < RankedTreeNode > children ) : FixedaryNode < RankedTreeNode > ( std::move ( children ) ), symbol ( symbol ), arity ( arity ) {
+			if ( getChildren ( ).size ( ) != arity )
+				throw "Arity != size";
+		}
+
+		char getSymbol ( ) const {
+			return symbol;
+		}
+
+	};
+
+	class RankedTree {
+		RankedTreeNode root;
+	};
+
+public:
+	void setUp ( );
+	void tearDown ( );
+
+	void testRegexps ( );
+	void testRankedTree ( );
+	void testUnrankedTree ( );
+};
+
+#endif // TREE_TEST_BASE_H_
diff --git a/alib2std/test-src/extensions/TreeTest.cpp b/alib2std/test-src/extensions/TreeTest.cpp
index c9e3d92790..024cb09cf4 100644
--- a/alib2std/test-src/extensions/TreeTest.cpp
+++ b/alib2std/test-src/extensions/TreeTest.cpp
@@ -9,61 +9,13 @@ void TreeTest::setUp ( ) {
 void TreeTest::tearDown ( ) {
 }
 
-void TreeTest::testRegexps ( ) {
-	RegExpIteration iter ( std::shared_ptr < RegExpElement > ( new RegExpEmpty ( ) ) );
-
-	CPPUNIT_ASSERT ( iter.getChild ( )->getParent ( ) == & iter );
-
-	RegExpIteration iter2 ( iter );
-	RegExpIteration iter3 ( iter2 );
-
-	CPPUNIT_ASSERT ( iter3.getChild ( )->getParent ( ) == & iter3 );
-
-	iter3 = iter;
-	RegExpIteration iter4 ( std::shared_ptr < RegExpElement > ( new RegExpEpsilon ( ) ) );
-	iter3 = iter4;
-
-	CPPUNIT_ASSERT ( iter3.getChild ( )->getParent ( ) == & iter3 );
-
-	RegExpSymbol s ( 'x' );
-	const RegExpSymbol & sr = s;
-	sr.getElements ( );
-}
-
-void TreeTest::testRankedTree ( ) {
-	RankedTreeNode node ( 'a', 1, { RankedTreeNode ( 'b', 1, { RankedTreeNode ( 'c', 0, { } ) } ) } );
-	const RankedTreeNode & cnode = node;
-
-	for ( const RankedTreeNode & child : cnode.getChildren ( ) )
-		CPPUNIT_ASSERT ( child.getParent ( ) == & cnode );
-}
-
-void TreeTest::testUnrankedTree ( ) {
-}
-
-void print_tree ( std::tree < char >::const_children_iterator biter, std::tree < char >::const_children_iterator eiter, std::string indent ) {
+void TreeTest::print_tree ( std::tree < char >::const_children_iterator biter, std::tree < char >::const_children_iterator eiter, std::string indent ) {
 	for ( std::tree < char >::const_children_iterator iter = biter; iter != eiter; iter++ ) {
 		std::cout << indent << * iter << std::endl;
 		print_tree ( iter.begin ( ), iter.end ( ), indent + " " );
 	}
 }
 
-struct RankedArityChecker {
-	bool operator ()( char symbol, unsigned wantedRank ) const {
-		switch ( symbol ) {
-		case 'a':
-			return wantedRank == 2;
-
-		case 'b':
-			return wantedRank == 1;
-
-		default:
-			return wantedRank == 0;
-		}
-	}
-
-};
-
 void TreeTest::testTreeStdStructure ( ) {
 	std::tree < char > t ( 'a', std::tree < char > ( 'a' ), std::tree < char > ( 'b', std::tree < char > ( 'a' ), std::tree < char > ( 'b' ) ) );
 
diff --git a/alib2std/test-src/extensions/TreeTest.h b/alib2std/test-src/extensions/TreeTest.h
index 12989ce280..77dd87a192 100644
--- a/alib2std/test-src/extensions/TreeTest.h
+++ b/alib2std/test-src/extensions/TreeTest.h
@@ -7,100 +7,31 @@
 
 class TreeTest : public CppUnit::TestFixture {
 	CPPUNIT_TEST_SUITE ( TreeTest );
-	CPPUNIT_TEST ( testRegexps );
-	CPPUNIT_TEST ( testRankedTree );
-	CPPUNIT_TEST ( testUnrankedTree );
 	CPPUNIT_TEST ( testTreeStdStructure );
 	CPPUNIT_TEST_SUITE_END ( );
 
 public:
-	class RegExpElement : public std::BaseNode < RegExpElement > {
-	};
-
-	class RegExpAlternation : public RegExpElement {
-	};
-
-	class RegExpConcatenation : public RegExpElement, public std::BinaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpConcatenation > {
-	public:
-		RegExpConcatenation ( std::shared_ptr < RegExpElement > left, std::shared_ptr < RegExpElement > right ) : BinaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpConcatenation > ( std::move ( left ), std::move ( right ) ) {
-		}
+	struct RankedArityChecker {
+		bool operator ()( char symbol, unsigned wantedRank ) const {
+			switch ( symbol ) {
+			case 'a':
+				return wantedRank == 2;
 
-	};
+			case 'b':
+				return wantedRank == 1;
 
-	class RegExpIteration : public RegExpElement, public std::UnaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpIteration > {
-	public:
-		RegExpIteration ( std::shared_ptr < RegExpElement > element ) : UnaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpIteration > ( std::move ( element ) ) {
+			default:
+				return wantedRank == 0;
+			}
 		}
 
 	};
 
-	class RegExpSymbol : public RegExpElement, public std::NullaryNode < std::shared_ptr < RegExpElement >, std::shared_ptr < const RegExpElement >, RegExpSymbol > {
-		char symbol;
-
-	public:
-		RegExpSymbol ( char symbol ) : symbol ( symbol ) {
-		}
-
-		char getSymbol ( ) const {
-			return symbol;
-		}
-
-	};
-
-	class RegExpEpsilon : public RegExpElement {
-	};
-
-	class RegExpEmpty : public RegExpElement {
-	};
-
-	class RegExp {
-		std::shared_ptr < RegExpElement > root;
-	};
-
-	class UnrankedTreeNode : public std::BaseNode < UnrankedTreeNode >, public std::VararyNode < UnrankedTreeNode > {
-		char symbol;
+	void print_tree ( std::tree < char >::const_children_iterator biter, std::tree < char >::const_children_iterator eiter, std::string indent );
 
-	public:
-		UnrankedTreeNode ( char symbol, std::vector < UnrankedTreeNode > children ) : VararyNode < UnrankedTreeNode > ( std::move ( children ) ), symbol ( symbol ) {
-		}
-
-		char getSymbol ( ) const {
-			return symbol;
-		}
-
-	};
-
-	class UnrankedTree {
-		UnrankedTreeNode root;
-	};
-
-	class RankedTreeNode : public std::BaseNode < RankedTreeNode >, public std::FixedaryNode < RankedTreeNode > {
-		char symbol;
-		char arity;
-
-	public:
-		RankedTreeNode ( char symbol, unsigned arity, std::vector < RankedTreeNode > children ) : FixedaryNode < RankedTreeNode > ( std::move ( children ) ), symbol ( symbol ), arity ( arity ) {
-			if ( getChildren ( ).size ( ) != arity )
-				throw "Arity != size";
-		}
-
-		char getSymbol ( ) const {
-			return symbol;
-		}
-
-	};
-
-	class RankedTree {
-		RankedTreeNode root;
-	};
-
-public:
 	void setUp ( );
 	void tearDown ( );
 
-	void testRegexps ( );
-	void testRankedTree ( );
-	void testUnrankedTree ( );
 	void testTreeStdStructure();
 };
 
-- 
GitLab