#pragma once #include #include #include "unit_schema.hpp" namespace saw { namespace impl { template class unit_matching; template class unit_redux_list { static_assert(sizeof...(T) == 0u, "Template type not supported"); using Type = unit_redux_list<>; }; template struct unit_redux_list, schema::UnitElement...> { using Type = typename unit_matching, schema::UnitElement...>, unit_redux_list<>>::TypeList; }; template class unit_matching_reduce { public: static_assert(always_false, "Template type not supported"); }; /** * Iterate over the left list to check against the left element. */ template class unit_matching_reduce, unit_redux_list,schema::UnitElement...>, unit_redux_list...>> { public: static constexpr bool is_same = std::is_same_v; // Match T,E against T0,E0 using ReducedType = typename std::conditional, schema::UnitElement>::type; using ReducedTypeList = typename std::conditional...>, unit_redux_list..., schema::UnitElement>>::type; using NextMatcher = unit_matching_reduce...>, ReducedTypeList>; using Type = typename NextMatcher::Type; using TypeList = typename NextMatcher::TypeList; static constexpr int64_t Num = NextMatcher::Num; }; /** * Final step after going through the list. This contains the final match result. * On the left is the accumulated type and on the right its's a list of non matching types */ template class unit_matching_reduce, unit_redux_list<>, unit_redux_list...>> { public: using Type = schema::UnitElement; using TypeList = unit_redux_list...>; static constexpr int64_t Num = E; }; template class unit_matching { static_assert(always_false, "Template type not supported"); }; template class unit_matching, unit_redux_list> { public: using TypeList = unit_redux_list; }; template class unit_matching, unit_redux_list> { public: // static constexpr bool is_same = std::is_same_v; using MatchReducer = unit_matching_reduce, unit_redux_list<>>; using ReducedType = typename MatchReducer::Type; using ReducedTypeList = typename MatchReducer::TypeList; static constexpr int64_t Num = MatchReducer::Num; using TypeRightList = typename std::conditional, unit_redux_list>::type; using TypeList = typename unit_matching::TypeList; }; template class unit_add_base { static_assert(always_false, "Template type not supported"); }; template class unit_add_base> { public: using Schema = schema::Unit; }; } template struct unit_element_reduction { using TypeList = typename impl::unit_matching, impl::unit_redux_list<>>::TypeList; using Schema = typename impl::unit_add_base::Schema; }; template struct unit_multiplication { static_assert(always_false, "Template type not supported"); }; template struct unit_multiplication< schema::Unit...>, schema::Unit...> > { using Schema = typename unit_element_reduction..., schema::UnitElement...>::Schema; }; template struct unit_division { static_assert(always_false, "Template type not supported"); }; template struct unit_division< schema::Unit...>, schema::Unit...> > { using Schema = typename unit_element_reduction..., schema::UnitElement...>::Schema; }; }