key_list.cpp serif/utils/dependencies/key_list.hpp serif/utils/dependencies/key_list_operations.hpp type_traits utility #include"serif/utils/dependencies/key_list.hpp" #include"serif/utils/dependencies/key_list_operations.hpp" #include<type_traits> #include<utility> namespace{ namespacedependencies=serif::utils::dependencies; namespacetypes=serif::utils::types; structEnthalpy{}; structEntropy{}; structElectronFraction{}; structDensity{}; structMissingKey{}; structEnthalpyTerm{}; structMaterialTerm{}; structDensityTerm{}; usingEmpty=dependencies::KeyList<>; usingSurfaceInputs=dependencies::KeyList<Enthalpy,Entropy,ElectronFraction>; usingDuplicateInputs=dependencies::KeyList<Enthalpy,Enthalpy>; usingMissingInput=dependencies::KeyList<Enthalpy,MissingKey>; template<typenameKeyT,typenameKeysT> conceptCanIndex=requires { dependencies::key_index<KeyT,KeysT>(); }; static_assert(dependencies::ContainsKey<Entropy,SurfaceInputs>); static_assert(dependencies::ContainsKey<Entropy,constSurfaceInputs&>); static_assert(!dependencies::ContainsKey<MissingKey,SurfaceInputs>); static_assert(!dependencies::ContainsKey<Enthalpy,Empty>); static_assert(!dependencies::ContainsKey<Enthalpy,DuplicateInputs>); static_assert(!dependencies::ContainsKey<Enthalpy,int>); static_assert(dependencies::key_count_v<Empty>==0); static_assert(dependencies::key_count_v<constSurfaceInputs&>==3); static_assert(dependencies::key_index<Enthalpy,SurfaceInputs>()==0); static_assert(dependencies::key_index<ElectronFraction,constSurfaceInputs&>()==2); static_assert(!CanIndex<MissingKey, SurfaceInputs>); static_assert(!CanIndex<Enthalpy, Empty>); static_assert(!CanIndex<Enthalpy, DuplicateInputs>); static_assert(!CanIndex<Enthalpy, int>); //Bindingorderdiffersfromdeclarationorder,anddensityisavailablebutnotrequired. usingAvailable=dependencies::Bindings< dependencies::Binding<ElectronFraction,MaterialTerm>, dependencies::Binding<Density,DensityTerm>, dependencies::Binding<Enthalpy,EnthalpyTerm>, dependencies::Binding<Entropy,MaterialTerm> >; usingIncomplete=dependencies::Bindings<dependencies::Binding<Enthalpy,EnthalpyTerm>>; usingDuplicateBindings=dependencies::Bindings< dependencies::Binding<Enthalpy,EnthalpyTerm>, dependencies::Binding<Enthalpy,MaterialTerm> >; template<typenameBindingsT,typenameKeysT> conceptCanResolve=requires{ typenamedependencies::ResolvedTargets<BindingsT,KeysT>; }; static_assert(dependencies::IsKeyList<Empty>); static_assert(dependencies::IsKeyList<SurfaceInputs>); static_assert(dependencies::IsKeyList<constvolatileSurfaceInputs&>); static_assert(!dependencies::IsKeyList<DuplicateInputs>); static_assert(!dependencies::IsKeyList<int>); static_assert(std::is_same_v<SurfaceInputs::Keys,types::TypeList<Enthalpy,Entropy,ElectronFraction>>); static_assert(dependencies::SatisfiesKeyList<Available,SurfaceInputs>); static_assert(dependencies::SatisfiesKeyList<constvolatileAvailable&,constSurfaceInputs&>); static_assert(dependencies::SatisfiesKeyList<Available&&,SurfaceInputs&&>); static_assert(!dependencies::SatisfiesKeyList<Incomplete,SurfaceInputs>); static_assert(!dependencies::SatisfiesKeyList<Available,MissingInput>); static_assert(!dependencies::SatisfiesKeyList<Available,DuplicateInputs>); static_assert(!dependencies::SatisfiesKeyList<DuplicateBindings,SurfaceInputs>); static_assert(!dependencies::SatisfiesKeyList<int,SurfaceInputs>); static_assert(!dependencies::SatisfiesKeyList<Available,int>); //Distinctphysicalinputsremaindistinctentriesevenwhentheyshareatargettype. usingSurfaceTargets=types::TypeList<EnthalpyTerm,MaterialTerm,MaterialTerm>; static_assert(std::is_same_v<dependencies::ResolvedTargets<Available,SurfaceInputs>,SurfaceTargets>); static_assert(std::is_same_v<dependencies::ResolvedTargets<constvolatileAvailable&,constSurfaceInputs&>,SurfaceTargets>); static_assert(std::is_same_v< dependencies::ResolvedTargets<Available,dependencies::KeyList<Entropy,Enthalpy>>, types::TypeList<MaterialTerm,EnthalpyTerm> >); static_assert(dependencies::SatisfiesKeyList<dependencies::Bindings<>,Empty>); static_assert(dependencies::SatisfiesKeyList<Available,Empty>); static_assert(std::is_same_v<dependencies::ResolvedTargets<dependencies::Bindings<>,Empty>,types::TypeList<>>); static_assert(std::is_same_v<dependencies::ResolvedTargets<Available,Empty>,types::TypeList<>>); static_assert(!dependencies::SatisfiesKeyList<DuplicateBindings,Empty>); static_assert(!dependencies::SatisfiesKeyList<int,Empty>); //Normalizethecontainers,whilepreservingtheexactkeyandtargettypestheycontain. usingQualifiedInputs=dependencies::KeyList<constEnthalpy,Enthalpy&>; usingQualifiedBindings=dependencies::Bindings< dependencies::Binding<constEnthalpy,constdouble&>, dependencies::Binding<Enthalpy&,void> >; static_assert(dependencies::IsKeyList<QualifiedInputs>); static_assert(dependencies::key_index<constEnthalpy,QualifiedInputs>()==0); static_assert(dependencies::key_index<Enthalpy&,QualifiedInputs>()==1); static_assert(!CanIndex<Enthalpy, QualifiedInputs>); static_assert(dependencies::IsKeyList<dependencies::KeyList<Enthalpy,constEnthalpy>>); static_assert(dependencies::SatisfiesKeyList<QualifiedBindings,QualifiedInputs>); static_assert(!dependencies::SatisfiesKeyList<Available,QualifiedInputs>); static_assert(!dependencies::SatisfiesKeyList<QualifiedBindings,dependencies::KeyList<Enthalpy>>); static_assert(std::is_same_v<dependencies::ResolvedTargets<QualifiedBindings,QualifiedInputs>,types::TypeList<constdouble&,void>>); //Unsupportedresolutionmustfailarequirementwithoutproducingahardcompilererror. static_assert(CanResolve<Available, SurfaceInputs>); static_assert(CanResolve<dependencies::Bindings<>,Empty>); static_assert(!CanResolve<Incomplete, SurfaceInputs>); static_assert(!CanResolve<Available, MissingInput>); static_assert(!CanResolve<Available, DuplicateInputs>); static_assert(!CanResolve<DuplicateBindings, SurfaceInputs>); static_assert(!CanResolve<int, SurfaceInputs>); static_assert(!CanResolve<Available, int>); static_assert(!CanResolve<int, Empty>); static_assert(!CanResolve<DuplicateBindings, Empty>); static_assert(!CanResolve<Available, QualifiedInputs>); //Fullmodelgraphsmaycontainmorekeysthanthecompiler'sdefaultfold-expressiondepth. template<std::size_tIndex> structLargeKey{}; template<std::size_t...Indices> autolarge_keys(std::index_sequence<Indices...>)->dependencies::KeyList<LargeKey<Indices>...>; template<std::size_t...Indices> autoduplicate_large_keys(std::index_sequence<Indices...>)->dependencies::KeyList<LargeKey<Indices>...,LargeKey<299>>; usingLarge=decltype(large_keys(std::make_index_sequence<300>{})); usingDuplicateLarge=decltype(duplicate_large_keys(std::make_index_sequence<300>{})); static_assert(!dependencies::IsKeyList<DuplicateLarge>); static_assert(dependencies::IsKeyList<dependencies::KeyList<LargeKey<0>,constLargeKey<0>,LargeKey<0>&>>); static_assert(!dependencies::IsKeyList<dependencies::KeyList<constLargeKey<0>,LargeKey<0>&,constLargeKey<0>>>); usingExtended=dependencies::CombinedKeyList<Large,dependencies::KeyList<LargeKey<0>,MissingKey>>; static_assert(dependencies::ContainsKey<LargeKey<299>,Large>); static_assert(!dependencies::ContainsKey<MissingKey,Large>); static_assert(dependencies::key_index<LargeKey<299>,Large>()==299); static_assert(dependencies::detail::key_list_subset_v<Large,Large>); static_assert(dependencies::detail::key_list_subset_v<Empty,Large>); static_assert(!dependencies::detail::key_list_subset_v<Large,Empty>); static_assert(!dependencies::detail::key_list_subset_v<dependencies::KeyList<MissingKey>,Large>); static_assert(dependencies::key_count_v<Extended>==301); static_assert(dependencies::key_index<LargeKey<0>,Extended>()==0); static_assert(dependencies::key_index<LargeKey<299>,Extended>()==299); static_assert(dependencies::key_index<MissingKey,Extended>()==300); }