template<typename T>
concept MagConstant = SymbolicConstant<T> && is-derived-from-specialization-of<T, mag_constant>();
template<typename T>
concept UnitMagnitude = (is-specialization-of<T, unit-magnitude>());
template<typename T>
concept MagArg = std::integral<T> || MagConstant<T>; // exposition only
template<UnitMagnitude M>
friend consteval UnitMagnitude auto operator*(unit-magnitude lhs, M rhs);
friend consteval auto operator/(unit-magnitude lhs, UnitMagnitude auto rhs);
template<UnitMagnitude Rhs>
friend consteval bool operator==(unit-magnitude, Rhs);
template<int Num, int Den = 1>
friend consteval auto pow(unit-magnitude base); // exposition only
template<MagArg auto V>
constexpr UnitMagnitude auto mag = see below;
template<std::intmax_t N, std::intmax_t D>
requires(N > 0)
constexpr UnitMagnitude auto mag_ratio = see below;
template<MagArg auto Base, int Num, int Den = 1>
constexpr UnitMagnitude auto mag_power = pow<Num, Den>(mag<Base>);
friend consteval bool is-positive-integral-power(unit-magnitude x); // exposition only
template<auto... Ms2>
friend consteval auto common-magnitude(unit-magnitude, unit-magnitude<Ms2...>); // exposition only
template<typename T>
concept Unit = SymbolicConstant<T> && std::derived_from<T, unit-interface>;
template<typename T>
concept PrefixableUnit = Unit<T> && is-derived-from-specialization-of<T, named_unit>();
template<typename T>
concept AssociatedUnit = Unit<U> && has-associated-quantity(U{});
template<typename U, auto QS>
concept UnitOf = AssociatedUnit<U> && QuantitySpec<decltype(QS)> &&
QuantitySpecConvertibleTo<get_quantity_spec(U{}), QS> &&
(get_kind(QS) == get_kind(get_quantity_spec(U{})) ||
!NestedQuantityKindSpecOf<get_quantity_spec(U{}), QS>);
template<auto From, auto To>
concept UnitConvertibleTo = // exposition only
Unit<decltype(From)> && Unit<decltype(To)> && (convertible(From, To));
template<typename U, auto FromU, auto QS>
concept UnitCompatibleWith = // exposition only
Unit<U> && Unit<decltype(FromU)> && QuantitySpec<decltype(QS)> &&
(!AssociatedUnit<U> || UnitOf<U, QS>) && UnitConvertibleTo<FromU, U{}>;
template<typename T>
concept OffsetUnit = Unit<T> && requires { T::point-origin; }; // exposition only
template<typename From, typename To>
concept PotentiallyConvertibleTo = // exposition only
Unit<From> && Unit<To> &&
((AssociatedUnit<From> && AssociatedUnit<To> &&
implicitly_convertible(get_quantity_spec(From{}), get_quantity_spec(To{}))) ||
(!AssociatedUnit<From> && !AssociatedUnit<To>));
template<UnitMagnitude M, Unit U>
friend consteval Unit auto operator*(M, U u);
friend consteval Unit auto operator*(Unit auto, UnitMagnitude auto) = delete;
template<UnitMagnitude M, Unit U>
friend consteval Unit auto operator/(M mag, U u);
consteval QuantitySpec auto get_quantity_spec(AssociatedUnit auto u);
consteval Unit auto get_unit(AssociatedUnit auto u);
template<AssociatedUnit U>
consteval auto get-associated-quantity(U u); // exposition only