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