Skip to content
Snippets Groups Projects
Commit 360828f0 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

support casting ranked to unranked (forward_)tree

parent ccb3d08c
No related branches found
No related tags found
No related merge requests found
...@@ -34,6 +34,20 @@ class forward_tree { ...@@ -34,6 +34,20 @@ class forward_tree {
tree_node ( T && data, std::vector < tree_node > && children ) : data ( std::move ( data ) ), children ( std::move ( children ) ) { 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 { ~tree_node ( ) noexcept {
} }
   
...@@ -454,6 +468,20 @@ public: ...@@ -454,6 +468,20 @@ public:
friend class forward_tree; 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: private:
...@@ -537,6 +565,16 @@ public: ...@@ -537,6 +565,16 @@ public:
insert_helper ( begin ( ), begin ( ).end ( ), begin, end ); 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 { const_children_iterator begin ( ) const {
...@@ -744,6 +782,9 @@ public: ...@@ -744,6 +782,9 @@ public:
return os; return os;
} }
   
template < class R, class AnotherArityChecker >
friend class forward_tree;
}; };
   
template < class T, class ... Ts > template < class T, class ... Ts >
......
...@@ -39,6 +39,24 @@ class tree { ...@@ -39,6 +39,24 @@ class tree {
child.parent = this; 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 { ~tree_node ( ) noexcept {
} }
   
...@@ -473,6 +491,20 @@ public: ...@@ -473,6 +491,20 @@ public:
friend class tree; 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: private:
...@@ -562,6 +594,16 @@ public: ...@@ -562,6 +594,16 @@ public:
insert_helper ( begin ( ), begin ( ).end ( ), begin, end ); 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 { const_children_iterator begin ( ) const {
...@@ -786,6 +828,9 @@ public: ...@@ -786,6 +828,9 @@ public:
return os; return os;
} }
   
template < class R, class AnotherArityChecker >
friend class tree;
}; };
   
template < class T, class ... Ts > template < class T, class ... Ts >
......
...@@ -113,6 +113,17 @@ void ForwardTreeTest::testTreeStdStructure ( ) { ...@@ -113,6 +113,17 @@ void ForwardTreeTest::testTreeStdStructure ( ) {
std::forward_tree < char, RankedArityChecker > rt2 ( 'c' ); std::forward_tree < char, RankedArityChecker > rt2 ( 'c' );
swap ( rt, rt2 ); 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::cout << rt << std::endl;
std::stringstream ss3; std::stringstream ss3;
ss3 << rt; ss3 << rt;
......
...@@ -124,6 +124,17 @@ void TreeTest::testTreeStdStructure ( ) { ...@@ -124,6 +124,17 @@ void TreeTest::testTreeStdStructure ( ) {
std::tree < char, RankedArityChecker > rt2 ( 'c' ); std::tree < char, RankedArityChecker > rt2 ( 'c' );
swap ( rt, rt2 ); 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 ( ) ); CPPUNIT_ASSERT ( rt.checkStructure ( ) );
std::cout << rt << std::endl; std::cout << rt << std::endl;
std::stringstream ss3; std::stringstream ss3;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment