diff --git a/alib2std/src/extensions/forward_tree.hpp b/alib2std/src/extensions/forward_tree.hpp index 00970e372111edaf873491986d8b1752e99d03e3..38ccdc105b582e16438a374a0d5c33ec074b466e 100644 --- a/alib2std/src/extensions/forward_tree.hpp +++ b/alib2std/src/extensions/forward_tree.hpp @@ -34,6 +34,20 @@ class forward_tree { tree_node ( T && data, std::vector < tree_node > && children ) : data ( std::move ( data ) ), children ( std::move ( children ) ) { } + template < class AnotherArityChecker > + tree_node ( const typename forward_tree < T, AnotherArityChecker >::tree_node & node, const AnotherArityChecker & arityChecker ) : data ( node.data ), children ( ) { + // INFO: The AnotherArityChecker parameter is there only to deduce the template parameter, it cannot be used to check that resulting tree_node comply with the arity checker of the resulting tree because it is different + for ( const typename forward_tree < T, AnotherArityChecker >::tree_node & child : node.children ) + children.push_back ( tree_node ( child, arityChecker ) ); + } + + template < class AnotherArityChecker > + tree_node ( typename forward_tree < T, AnotherArityChecker >::tree_node && node, const AnotherArityChecker & arityChecker ) : data ( std::move ( node.data ) ), children ( ) { + // INFO: The AnotherArityChecker parameter is there only to deduce the template parameter, it cannot be used to check that resulting tree_node comply with the arity checker of the resulting tree because it is different + for ( typename forward_tree < T, AnotherArityChecker >::tree_node & child : node.children ) + children.push_back ( tree_node ( std::move ( child ), arityChecker ) ); + } + ~tree_node ( ) noexcept { } @@ -454,6 +468,20 @@ public: friend class forward_tree; }; +// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + void checkArities ( const tree_node & node ) const { + if ( !arityChecker ( node.getData ( ), node.getChildren ( ).size ( ) ) ) + throw std::length_error ( "Invalid number of children" ); + + for ( const tree_node & child : node.getChildren ( ) ) + checkArities ( child ); + } + + void checkArities ( ) const { + return checkArities ( root ); + } + // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- private: @@ -537,6 +565,16 @@ public: insert_helper ( begin ( ), begin ( ).end ( ), begin, end ); } + template < class AnotherArityChecker = AnyArity < T > > + forward_tree ( const forward_tree < T, AnotherArityChecker > & other, ArityChecker arityChecker = ArityChecker ( ) ) : arityChecker ( arityChecker ), root ( other.root, AnotherArityChecker ( ) ) { + checkArities ( ); + } + + template < class AnotherArityChecker = AnyArity < T > > + forward_tree ( forward_tree < T, AnotherArityChecker > && other, ArityChecker arityChecker = ArityChecker ( ) ) : arityChecker ( arityChecker ), root ( std::move ( other.root ), AnotherArityChecker ( ) ) { + checkArities ( ); + } + // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- const_children_iterator begin ( ) const { @@ -744,6 +782,9 @@ public: return os; } + template < class R, class AnotherArityChecker > + friend class forward_tree; + }; template < class T, class ... Ts > diff --git a/alib2std/src/extensions/tree.hpp b/alib2std/src/extensions/tree.hpp index 61df0b725bd63b8067add994084e6dcb571ceeab..653b3a77139b9031f73c180a1167b59d09c9cfc0 100644 --- a/alib2std/src/extensions/tree.hpp +++ b/alib2std/src/extensions/tree.hpp @@ -39,6 +39,24 @@ class tree { child.parent = this; } + template < class AnotherArityChecker > + tree_node ( const typename tree < T, AnotherArityChecker >::tree_node & node, const AnotherArityChecker & arityChecker ) : data ( node.data ), parent ( nullptr ), children ( ) { + // INFO: The AnotherArityChecker parameter is there only to deduce the template parameter, it cannot be used to check that resulting tree_node comply with the arity checker of the resulting tree because it is different + for ( const typename tree < T, AnotherArityChecker >::tree_node & child : node.children ) { + children.push_back ( tree_node ( child, arityChecker ) ); + children [ children.size ( ) - 1 ].parent = this; + } + } + + template < class AnotherArityChecker > + tree_node ( typename tree < T, AnotherArityChecker >::tree_node && node, const AnotherArityChecker & arityChecker ) : data ( std::move ( node.data ) ), parent ( nullptr ), children ( ) { + // INFO: The AnotherArityChecker parameter is there only to deduce the template parameter, it cannot be used to check that resulting tree_node comply with the arity checker of the resulting tree because it is different + for ( typename tree < T, AnotherArityChecker >::tree_node & child : node.children ) { + children.push_back ( tree_node ( std::move ( child ), arityChecker ) ); + children [ children.size ( ) - 1 ].parent = this; + } + } + ~tree_node ( ) noexcept { } @@ -473,6 +491,20 @@ public: friend class tree; }; +// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + void checkArities ( const tree_node & node ) const { + if ( !arityChecker ( node.getData ( ), node.getChildren ( ).size ( ) ) ) + throw std::length_error ( "Invalid number of children" ); + + for ( const tree_node & child : node.getChildren ( ) ) + checkArities ( child ); + } + + void checkArities ( ) const { + return checkArities ( root ); + } + // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- private: @@ -562,6 +594,16 @@ public: insert_helper ( begin ( ), begin ( ).end ( ), begin, end ); } + template < class AnotherArityChecker = AnyArity < T > > + tree ( const tree < T, AnotherArityChecker > & other, ArityChecker arityChecker = ArityChecker ( ) ) : arityChecker ( arityChecker ), root ( other.root, AnotherArityChecker ( ) ) { + checkArities ( ); + } + + template < class AnotherArityChecker = AnyArity < T > > + tree ( tree < T, AnotherArityChecker > && other, ArityChecker arityChecker = ArityChecker ( ) ) : arityChecker ( arityChecker ), root ( std::move ( other.root ), AnotherArityChecker ( ) ) { + checkArities ( ); + } + // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- const_children_iterator begin ( ) const { @@ -786,6 +828,9 @@ public: return os; } + template < class R, class AnotherArityChecker > + friend class tree; + }; template < class T, class ... Ts > diff --git a/alib2std/test-src/extensions/ForwardTreeTest.cpp b/alib2std/test-src/extensions/ForwardTreeTest.cpp index f039c6a89aef4a185d7980d95d59453186bab78f..81f69c8d8e28035257615038780697e033990d77 100644 --- a/alib2std/test-src/extensions/ForwardTreeTest.cpp +++ b/alib2std/test-src/extensions/ForwardTreeTest.cpp @@ -113,6 +113,17 @@ void ForwardTreeTest::testTreeStdStructure ( ) { std::forward_tree < char, RankedArityChecker > rt2 ( 'c' ); swap ( rt, rt2 ); + std::forward_tree < char > rt2unranked ( rt2 ); + + std::forward_tree < char, RankedArityChecker > rt3 ( rt2unranked ); + + CPPUNIT_ASSERT ( rt2 == rt3 ); + + rt2unranked.push_back ( rt2unranked.begin ( ), 'f' ); + + typedef std::forward_tree < char, RankedArityChecker > rankedforwardtree; + CPPUNIT_ASSERT_THROW ( ( void ) rankedforwardtree ( rt2unranked ), std::length_error); + std::cout << rt << std::endl; std::stringstream ss3; ss3 << rt; diff --git a/alib2std/test-src/extensions/TreeTest.cpp b/alib2std/test-src/extensions/TreeTest.cpp index 024cb09cf482273f4b57615590557836ad2479a8..1806d96947bc20eb96f9532712cf2d5242b2d606 100644 --- a/alib2std/test-src/extensions/TreeTest.cpp +++ b/alib2std/test-src/extensions/TreeTest.cpp @@ -124,6 +124,17 @@ void TreeTest::testTreeStdStructure ( ) { std::tree < char, RankedArityChecker > rt2 ( 'c' ); swap ( rt, rt2 ); + std::tree < char > rt2unranked ( rt2 ); + + std::tree < char, RankedArityChecker > rt3 ( rt2unranked ); + + CPPUNIT_ASSERT ( rt2 == rt3 ); + + rt2unranked.push_back ( rt2unranked.begin ( ), 'f' ); + + typedef std::tree < char, RankedArityChecker > rankedforwardtree; + CPPUNIT_ASSERT_THROW ( ( void ) rankedforwardtree ( rt2unranked ), std::length_error); + CPPUNIT_ASSERT ( rt.checkStructure ( ) ); std::cout << rt << std::endl; std::stringstream ss3;