incremental_computation.hpp array concepts functional type_traits utility serif/utils/dependencies/computation.hpp serif/utils/dependencies/detail/result.hpp serif/utils/dependencies/detail/type_lists.hpp src/compile_time_checks/serif/utils/dependencies/computation_graph.cpp src/include/serif/utils/dependencies/dependencies.hpp serif::utils::dependencies::ComputationUpdate serif::utils::dependencies::IncrementalComputation serif serif::utils serif::utils::dependencies #pragmaonce #include<array> #include<concepts> #include<functional> #include<type_traits> #include<utility> #include"serif/utils/dependencies/computation.hpp" #include"serif/utils/dependencies/detail/result.hpp" #include"serif/utils/dependencies/detail/type_lists.hpp" namespaceserif::utils::dependencies{ template<IsKeyListInputsT,typenameValueT> structComputationUpdate{ constValueT*previous{nullptr}; std::array<bool,detail::KeyListSize<InputsT>::value>changed_inputs{}; boolrebuild{false}; template<typenameKeyT>requiresdetail::contains_key_v<KeyT, InputsT> [[nodiscard]]boolchanged()const{ returnprevious==nullptr||rebuild||changed_inputs[detail::type_index<KeyT>(typenameInputsT::Keys{})]; } }; template<typenameKeyT,typenameValueT,IsKeyListInputsT,typenameFunctionT> requiresstd::is_object_v<ValueT>&&std::move_constructible<ValueT> classIncrementalComputation{ public: usingKey=KeyT; usingInputs=std::remove_cvref_t<InputsT>; usingFunction=FunctionT; usingUpdate=ComputationUpdate<Inputs, ValueT>; staticconstexprboolowns_inputs=false; explicitIncrementalComputation(FunctionTfunction):m_function(std::move(function)){} template<typename...Arguments> requiresstd::invocable<constFunctionT&,constUpdate&,constArguments&...>&& std::same_as<typenamedetail::Result<std::remove_cv_t<std::invoke_result_t<constFunctionT&,constUpdate&,constArguments&...>>>::Value,ValueT> [[nodiscard]]decltype(auto)evaluate(constArguments&...arguments)const{ returnevaluate_update(Update{},arguments...); } template<typename...Arguments> [[nodiscard]]decltype(auto)evaluate_update(constUpdate&update,constArguments&...arguments)const{ returnstd::invoke(m_function,update,arguments...); } private: FunctionTm_function; }; template<typenameKeyT,typenameValueT,typenameInputsT,typenameFunctionT> inlineconstexprboolis_computation_v<IncrementalComputation<KeyT, ValueT, InputsT, FunctionT>>=true; template<typenameKeyT,typenameValueT,IsKeyListInputsT,typenameFunctionT> requiresstd::is_object_v<ValueT>&&std::move_constructible<ValueT>&& std::constructible_from<std::decay_t<FunctionT>,FunctionT> [[nodiscard]]automake_incremental_computation(FunctionT&&function){ returnIncrementalComputation<KeyT, ValueT, std::remove_cvref_t<InputsT>,std::decay_t<FunctionT>>(std::forward<FunctionT>(function)); } }