contributions.hpp cstddef memory type_traits utility tuple serif/equations/concepts.hpp src/include/serif/backend/mfem/operators/volume_stages.hpp serif::operators::ContributionBinding serif::operators::detail::ContributionChildren serif serif::operators serif::operators::detail #pragmaonce #include<cstddef> #include<memory> #include<type_traits> #include<utility> #include<tuple> #include"serif/equations/concepts.hpp" namespaceserif::operators{ template<typenameEquationT> structContributionBinding{ std::shared_ptr<constEquationT>equation; doublecoefficient; }; namespacedetail{ template<typenameEquationT> structContributionChildren{ std::shared_ptr<constEquationT>parent; decltype(std::declval<constEquationT&>().contributions())values; explicitContributionChildren(std::shared_ptr<constEquationT>equation): parent(std::move(equation)), values(parent->contributions()){ } }; template<typenameEquationT> [[nodiscard]]autobind_contributions(std::shared_ptr<constEquationT>equation,doublecoefficient){ ifconstexpr(requires{equation->contributions();}){ constautochildren=std::make_shared<constContributionChildren<EquationT>>(std::move(equation)); returnstd::apply([&](constauto&...child){ //Aliasingpointersaddresseachchildbutretainthetupleanditsparenttogether. returnstd::tuple_cat(bind_contributions( std::shared_ptr<conststd::remove_cvref_t<decltype(child)>>(children,&child),coefficient )...); },children->values); }else{ returnstd::tuple{ContributionBinding<EquationT>{ .equation=std::move(equation), .coefficient=coefficient }}; } } template<typenameEquationT,typenameFunctionT> voidvisit_contributions( constEquationT&equation, FunctionT&function, std::size_t&index, doublecoefficient ){ ifconstexpr(requires{equation.contributions();}){ std::apply([&](constauto&...child){(visit_contributions(child,function,index,coefficient),...);},equation.contributions()); }else{ function(equation,index++,coefficient); } } }//namespacedetail template<equations::EquationEquationT> [[nodiscard]]autobind_contributions(std::shared_ptr<constEquationT>equation){ returndetail::bind_contributions(std::move(equation),1.0); } template<equations::EquationEquationT,typenameFunctionT> voidfor_each_contribution( constEquationT&equation, FunctionT&&function ){ std::size_tindex=0; detail::visit_contributions(equation,function,index,1.0); } }//namespaceserif::operators