refactor: type_name_less introduced and used as a default predicate for expression templates

This commit is contained in:
Mateusz Pusz
2024-11-26 10:09:28 +01:00
parent 360cf7d540
commit 3b14b588e9
6 changed files with 26 additions and 44 deletions

View File

@@ -80,7 +80,7 @@ template<AssociatedUnit U>
else if constexpr (requires { U::_reference_unit_; })
return determine_associated_quantity(U::_reference_unit_);
else if constexpr (requires { typename U::_num_; }) {
return expr_map<to_quantity_spec, derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(u);
return expr_map<to_quantity_spec, derived_quantity_spec, struct dimensionless>(u);
}
}

View File

@@ -10,6 +10,7 @@
import std;
#else
#include <string_view>
#include <type_traits>
#endif
#endif
@@ -37,6 +38,8 @@ template<typename T>
return name;
}
template<typename Lhs, typename Rhs>
struct type_name_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {};
// This is typically used to deterministically chose one of the alternatives
// to guarantee the commutation of the operation (e.g., `a + b` should return

View File

@@ -29,7 +29,6 @@
#include <mp-units/compat_macros.h>
#include <mp-units/ext/fixed_string.h>
#include <mp-units/ext/inplace_vector.h>
#include <mp-units/ext/type_name.h>
#include <mp-units/ext/type_traits.h>
#include <mp-units/framework/dimension_concepts.h>
#include <mp-units/framework/expression_template.h>
@@ -59,12 +58,6 @@ MP_UNITS_EXPORT struct dimension_one;
namespace detail {
template<typename Lhs, typename Rhs>
struct base_dimension_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {};
template<typename T1, typename T2>
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
template<typename... Expr>
struct derived_dimension_impl : expr_fractions<dimension_one, Expr...> {};
@@ -72,13 +65,13 @@ struct dimension_interface {
template<Dimension Lhs, Dimension Rhs>
[[nodiscard]] friend consteval Dimension auto operator*(Lhs, Rhs)
{
return expr_multiply<derived_dimension, struct dimension_one, type_list_of_base_dimension_less>(Lhs{}, Rhs{});
return expr_multiply<derived_dimension, struct dimension_one>(Lhs{}, Rhs{});
}
template<Dimension Lhs, Dimension Rhs>
[[nodiscard]] friend consteval Dimension auto operator/(Lhs, Rhs)
{
return expr_divide<derived_dimension, struct dimension_one, type_list_of_base_dimension_less>(Lhs{}, Rhs{});
return expr_divide<derived_dimension, struct dimension_one>(Lhs{}, Rhs{});
}
template<Dimension Lhs, Dimension Rhs>
@@ -197,8 +190,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Dimension D>
requires detail::non_zero<Den>
[[nodiscard]] consteval Dimension auto pow(D d)
{
return detail::expr_pow<Num, Den, derived_dimension, struct dimension_one, detail::type_list_of_base_dimension_less>(
d);
return detail::expr_pow<Num, Den, derived_dimension, struct dimension_one>(d);
}
/**

View File

@@ -25,6 +25,7 @@
#include <mp-units/bits/math_concepts.h>
#include <mp-units/bits/ratio.h>
#include <mp-units/bits/type_list.h>
#include <mp-units/ext/type_name.h>
#include <mp-units/ext/type_traits.h>
#ifndef MP_UNITS_IN_MODULE_INTERFACE
@@ -302,6 +303,8 @@ struct expr_less_impl<T, power<T, Ints...>, Pred> : std::true_type {};
template<typename Lhs, typename Rhs, template<typename, typename, auto...> typename Pred>
using expr_less = expr_less_impl<Lhs, Rhs, Pred>;
template<typename T1, typename T2>
using type_list_name_less = expr_less<T1, T2, type_name_less>;
// expr_fractions
template<typename Num = type_list<>, typename Den = type_list<>>
@@ -387,8 +390,8 @@ template<typename NumList, typename DenList, SymbolicArg OneType, template<typen
* @tparam Lhs lhs of the operation
* @tparam Rhs rhs of the operation
*/
template<template<typename...> typename To, SymbolicArg OneType, template<typename, typename> typename Pred,
typename Lhs, typename Rhs>
template<template<typename...> typename To, SymbolicArg OneType,
template<typename, typename> typename Pred = type_list_name_less, typename Lhs, typename Rhs>
[[nodiscard]] MP_UNITS_CONSTEVAL auto expr_multiply(Lhs, Rhs)
{
if constexpr (is_same_v<Lhs, OneType>) {
@@ -422,8 +425,8 @@ template<template<typename...> typename To, SymbolicArg OneType, template<typena
* @tparam Lhs lhs of the operation
* @tparam Rhs rhs of the operation
*/
template<template<typename...> typename To, SymbolicArg OneType, template<typename, typename> typename Pred,
typename Lhs, typename Rhs>
template<template<typename...> typename To, SymbolicArg OneType,
template<typename, typename> typename Pred = type_list_name_less, typename Lhs, typename Rhs>
[[nodiscard]] MP_UNITS_CONSTEVAL auto expr_divide(Lhs lhs, Rhs rhs)
{
if constexpr (is_same_v<Lhs, Rhs>) {
@@ -489,7 +492,7 @@ template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To
* @tparam T Expression being the base of the operation
*/
template<std::intmax_t Num, std::intmax_t Den, template<typename...> typename To, SymbolicArg OneType,
template<typename, typename> typename Pred, typename T>
template<typename, typename> typename Pred = type_list_name_less, typename T>
requires detail::non_zero<Den>
[[nodiscard]] consteval auto expr_pow(T v)
{
@@ -552,7 +555,7 @@ template<template<typename> typename Proj, template<typename...> typename To, Sy
* @tparam T expression template to map from
*/
template<template<typename> typename Proj, template<typename...> typename To, SymbolicArg OneType,
template<typename, typename> typename Pred, typename T>
template<typename, typename> typename Pred = type_list_name_less, typename T>
[[nodiscard]] consteval auto expr_map(T)
{
if constexpr (type_list_size<typename T::_num_> + type_list_size<typename T::_den_> == 0)

View File

@@ -106,12 +106,6 @@ template<auto... Args>
return ch;
}
template<NamedQuantitySpec Lhs, NamedQuantitySpec Rhs>
struct quantity_spec_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {};
template<typename T1, typename T2>
using type_list_of_quantity_spec_less = expr_less<T1, T2, quantity_spec_less>;
template<NamedQuantitySpec Q>
requires requires { Q::dimension; }
using to_dimension = MP_UNITS_NONCONST_TYPE(Q::dimension);
@@ -127,16 +121,14 @@ struct quantity_spec_interface_base {
[[nodiscard]] friend consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs)
{
return clone_kind_of<Lhs{}, Rhs{}>(
expr_multiply<derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(remove_kind(lhs),
remove_kind(rhs)));
expr_multiply<derived_quantity_spec, struct dimensionless>(remove_kind(lhs), remove_kind(rhs)));
}
template<QuantitySpec Lhs, QuantitySpec Rhs>
[[nodiscard]] friend consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
{
return clone_kind_of<Lhs{}, Rhs{}>(
expr_divide<derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(remove_kind(lhs),
remove_kind(rhs)));
expr_divide<derived_quantity_spec, struct dimensionless>(remove_kind(lhs), remove_kind(rhs)));
}
template<QuantitySpec Lhs, QuantitySpec Rhs>
@@ -433,8 +425,7 @@ struct derived_quantity_spec_impl :
using _base_type_ = derived_quantity_spec_impl;
using _base_ = expr_fractions<dimensionless, Expr...>;
static constexpr Dimension auto dimension =
expr_map<to_dimension, derived_dimension, struct dimension_one, type_list_of_base_dimension_less>(_base_{});
static constexpr Dimension auto dimension = expr_map<to_dimension, derived_dimension, struct dimension_one>(_base_{});
static constexpr quantity_character character =
derived_quantity_character(typename _base_::_num_{}, typename _base_::_den_{});
};
@@ -563,8 +554,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
[[nodiscard]] consteval QuantitySpec auto pow(Q q)
{
return detail::clone_kind_of<Q{}>(
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
detail::remove_kind(q)));
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless>(detail::remove_kind(q)));
}
@@ -1526,7 +1516,7 @@ template<QuantitySpec Q>
} else if constexpr (requires { Q::_parent_; }) {
return get_kind_tree_root(Q::_parent_);
} else if constexpr (DerivedQuantitySpec<Q>) {
return expr_map<to_kind, derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(q);
return expr_map<to_kind, derived_quantity_spec, struct dimensionless>(q);
} else {
// root quantity
return q;

View File

@@ -152,12 +152,6 @@ struct derived_unit;
namespace detail {
template<Unit Lhs, Unit Rhs>
struct unit_less : std::bool_constant<type_name<Lhs>() < type_name<Rhs>()> {};
template<typename T1, typename T2>
using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
struct unit_interface {
/**
* Multiplication by `1` returns the same unit, otherwise `scaled_unit` is being returned.
@@ -200,7 +194,7 @@ struct unit_interface {
template<Unit Lhs, Unit Rhs>
[[nodiscard]] friend MP_UNITS_CONSTEVAL Unit auto operator*(Lhs lhs, Rhs rhs)
{
return expr_multiply<derived_unit, struct one, type_list_of_unit_less>(lhs, rhs);
return expr_multiply<derived_unit, struct one>(lhs, rhs);
}
/**
@@ -211,7 +205,7 @@ struct unit_interface {
template<Unit Lhs, Unit Rhs>
[[nodiscard]] friend MP_UNITS_CONSTEVAL Unit auto operator/(Lhs lhs, Rhs rhs)
{
return expr_divide<derived_unit, struct one, type_list_of_unit_less>(lhs, rhs);
return expr_divide<derived_unit, struct one>(lhs, rhs);
}
template<Unit Lhs, Unit Rhs>
@@ -621,7 +615,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
requires detail::non_zero<Den>
[[nodiscard]] consteval Unit auto pow(U u)
{
return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u);
return detail::expr_pow<Num, Den, derived_unit, struct one>(u);
}
/**
@@ -696,7 +690,7 @@ template<Unit U1, Unit U2>
else if constexpr (is_positive_integral_power(canonical_rhs.mag / canonical_lhs.mag))
return u1;
else {
if constexpr (detail::unit_less<U1, U2>::value)
if constexpr (detail::type_name_less<U1, U2>::value)
return common_unit<U1, U2>{};
else
return common_unit<U2, U1>{};
@@ -730,7 +724,7 @@ struct collapse_common_unit_impl<List, NewUnit, true> {
template<Unit NewUnit, Unit... Us>
using collapse_common_unit = type_list_unique<
type_list_sort<typename collapse_common_unit_impl<type_list<>, NewUnit, false, Us...>::type, type_list_of_unit_less>>;
type_list_sort<typename collapse_common_unit_impl<type_list<>, NewUnit, false, Us...>::type, type_list_name_less>>;
} // namespace detail