graph.hpp array cstddef utility serif/utils/dependencies/detail/type_lists.hpp src/include/serif/utils/dependencies/computation_graph.hpp serif::utils::dependencies::detail::Graph serif serif::utils serif::utils::dependencies serif::utils::dependencies::detail #pragmaonce #include<array> #include<cstddef> #include<utility> #include"serif/utils/dependencies/detail/type_lists.hpp" namespaceserif::utils::dependencies::detail{ template<typename...Computations> structGraph{ staticconstexprstd::size_tsize=sizeof...(Computations); usingMask=std::array<bool,size>; usingMatrix=std::array<Mask,size>; usingOrder=std::array<std::size_t,size>; template<typenameComputationT> [[nodiscard]]staticconstevalMaskprerequisites(){ return{contains_key_v<typename Computations::Key, typename ComputationT::Inputs>...}; } staticconstexprMatrixedges{prerequisites<Computations>()...}; [[nodiscard]]staticconstevalOrdermake_order(){ Orderresult{}; result.fill(size); Maskvisited{}; for(std::size_tposition=0;position<size;++position){ for(std::size_tcandidate=0;candidate<size;++candidate){ if(visited[candidate]){continue;} boolready=true; for(std::size_tinput=0;input<size;++input){ if(edges[candidate][input]&&!visited[input]){ready=false;} } if(ready){ result[position]=candidate; visited[candidate]=true; break; } } } returnresult; } staticconstexprOrderorder=make_order(); [[nodiscard]]staticconstevalboolacyclic(){ for(conststd::size_tindex:order){ if(index==size){returnfalse;} } returntrue; } template<typename...Keys> [[nodiscard]]staticconstevalMaskrequired(KeyList<Keys...>){ Maskresult{(contains_key_v<typenameComputations::Key,KeyList<Keys...>>)...}; for(std::size_tpass=0;pass<size;++pass){ for(std::size_tuser=0;user<size;++user){ if(!result[user]){continue;} for(std::size_tinput=0;input<size;++input){ result[input]=result[input]||edges[user][input]; } } } returnresult; } }; }