/******************************************************************************/ /* VARIOUS ALGORITHMS *********************************************************/ /******************************************************************************/ #ifndef _H_EBCL_ALGORITHMS #define _H_EBCL_ALGORITHMS #include #include namespace ebcl { /*= VISITOR ==================================================================*/ /* Helper for the visitor algorithm. Provides the various types used internally * as well as means to create and dereference values for the stack. * * The template's default implementation are not functional. It is specialised * later for references and non-references. */ template< typename T_Ref , bool IsRef = std::is_reference< T_Ref >::value > struct T_VisitorHelper_ { using T_Opt = void; // Optional value type using T_StackRef = void; // Stack reference type static T_StackRef mkext( T_Ref ) noexcept; // Create stack reference static T_Ref deref( T_StackRef ) noexcept; // Dereference stack entry }; template< // Node type typename T_Node , // Node reference type; by default, use values for arithmetic types and // pointers, and references for other types typename R_Node = std::conditional_t< std::is_arithmetic< T_Node >::value || std::is_pointer< T_Node >::value , T_Node , T_Node& > > class T_Visitor { private: using Helper_ = T_VisitorHelper_< R_Node >; public: // Optional value using T_OptNode = typename Helper_::T_Opt; // Node browser. Returns the Nth child of the specified node, or null // if there are no children left. using F_NodeBrowser = std::function< T_OptNode( R_Node , uint32_t ) >; // Node action. Second parameter indicates whether the action is // being called before (false) or after (true) visiting the children. using F_NodeAction = std::function< bool( R_Node , bool ) >; private: using T_StackRef_ = typename Helper_::T_StackRef; // State of a stack entry enum E_State_ { BEFORE , // Must enter the node CHILDREN , // Going through children AFTER // Must exit the node }; struct T_NodeRef_ { T_StackRef_ node; uint32_t child; E_State_ state{ BEFORE }; explicit T_NodeRef_( R_Node node ) noexcept : node( Helper_::mkext( node ) ) , child( 0 ) {} explicit T_NodeRef_( R_Node node , uint32_t child ) noexcept : node( Helper_::mkext( node ) ) , child( child ) {} }; F_NodeBrowser nodeBrowser_; T_AutoArray< T_NodeRef_ , 8 > stack_; public: T_Visitor( ) = delete; T_Visitor( T_Visitor const& ) = default; T_Visitor( T_Visitor&& ) noexcept = default; explicit T_Visitor( F_NodeBrowser browser ) noexcept; void visit( R_Node root , F_NodeAction action ); }; } // namespace #endif // _H_EBCL_ALGORITHMS #include