contributions.hpp tuple type_traits utility serif/discretization/blocks/traits.hpp serif/discretization/forms/operands.hpp src/compile_time_checks/serif/operators/computation_owners.cpp src/include/serif/equations/angular_momentum.hpp src/include/serif/equations/barotropic_density.hpp src/include/serif/equations/barycenter.hpp src/include/serif/equations/concepts.hpp src/include/serif/equations/equations.hpp src/include/serif/equations/mass_normalization.hpp src/include/serif/equations/primal_gravity.hpp serif::equations::Contribution serif::equations::TestOperandTraits serif::equations::TestOperandTraits< T, std::void_t< typename T::TestOperand > > serif::equations::ContributionSupport serif::equations::ContributionSupport< T, std::void_t< typename T::Support > > serif::equations::Contributions serif::equations::ContributionTuple serif::equations::ContributionTuple< std::tuple< Ts... >, std::void_t< decltype(std::tuple_cat(std::declval< typename Contributions< std::remove_cvref_t< Ts > >::type >()...))> > serif::equations::Contributions< T, std::void_t< decltype(std::declval< const T & >().contributions())> > serif serif::equations File containing the Contribution struct. This is effectively a helper struct for authoring equations with fewer lines of boiler-plate. The idea here is that every equation must report certain members so that the backend can inspect at compile time. An author could certainly write these members themselves, but the Contribution struct auto generates those members based on its template parameters. Therefore, by inheriting from the Contribution struct an equation author can avoid writing those members themselves. Note that while this is inheritance it is still a compile-time relation. Contribution does not add any runtime overhead to the equation. Emily M. Boudreaux #pragmaonce #include<tuple> #include<type_traits> #include<utility> #include"serif/discretization/blocks/traits.hpp" #include"serif/discretization/forms/operands.hpp" namespaceserif::equations{ template<discretization::forms::IsOperandTestOperandT,typenameSupportT=discretization::blocks::SupportOf<typenameTestOperandT::term_type>> structContribution{ usingTest=TestOperandT::term_type; usingTestOperand=TestOperandT; usingSupport=SupportT; }; template<typenameT,typename=void> structTestOperandTraits{ usingtype=discretization::forms::Operand<typename T::Test>; }; template<typenameT> structTestOperandTraits<T,std::void_t<typenameT::TestOperand>>{ usingtype=T::TestOperand; }; template<typenameT> usingTestOperandOf=TestOperandTraits<T>::type; template<typenameT,typename=void> structContributionSupport{ usingtype=discretization::blocks::SupportOf<typename T::Test>; }; template<typenameT> structContributionSupport<T,std::void_t<typenameT::Support>>{ usingtype=T::Support; }; template<typenameT> usingSupportOf=ContributionSupport<T>::type; template<typenameT,typename=void> structContributions{ usingtype=std::tuple<T>; }; template<typenameTupleT,typename=void> structContributionTuple{ usingtype=void; }; template<typename...Ts> structContributionTuple<std::tuple<Ts...>,std::void_t<decltype(std::tuple_cat(std::declval<typenameContributions<std::remove_cvref_t<Ts>>::type>()...))>>{ usingtype=decltype(std::tuple_cat(std::declval<typenameContributions<std::remove_cvref_t<Ts>>::type>()...)); }; template<typenameT> structContributions<T,std::void_t<decltype(std::declval<constT&>().contributions())>>: ContributionTuple<std::remove_cvref_t<decltype(std::declval<constT&>().contributions())>>{}; template<typenameT> usingContributionsOf=Contributions<std::remove_cvref_t<T>>::type; }//namespaceserif::equations