template<typename T>
concept Dimension = SymbolicConstant<T> && std::derived_from<T, dimension-interface>;
template<typename T>
concept BaseDimension = // exposition only
Dimension<T> && (is-derived-from-specialization-of<T, base_dimension>());
template<typename T, auto D>
concept DimensionOf = Dimension<T> && Dimension<decltype(D)> && (T{} == D);
template<typename T>
concept QuantitySpec = SymbolicConstant<T> && std::derived_from<T, quantity-spec-interface>;
template<typename T>
concept QuantityKindSpec = // exposition only
QuantitySpec<T> && is-specialization-of<T, kind_of_>();
template<typename T>
concept NamedQuantitySpec = // exposition only
QuantitySpec<T> && is-derived-from-specialization-of<T, quantity_spec>() &&
(!QuantityKindSpec<T>);
template<typename T>
concept DerivedQuantitySpec = // exposition only
QuantitySpec<T> &&
(is-specialization-of<T, derived_quantity_spec>() ||
(QuantityKindSpec<T> &&
is-specialization-of<decltype(auto(T::quantity-spec)), derived_quantity_spec>()));
template<auto Child, auto Parent>
concept ChildQuantitySpecOf = (is-child-of(Child, Parent)); // exposition only
template<auto To, auto From>
concept NestedQuantityKindSpecOf = // exposition only
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> &&
(get_kind(From) != get_kind(To)) && ChildQuantitySpecOf<To, get_kind(From).quantity-spec>;
template<auto From, auto To>
concept QuantitySpecConvertibleTo = // exposition only
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> && implicitly_convertible(From, To);
template<auto From, auto To>
concept QuantitySpecExplicitlyConvertibleTo = // exposition only
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> && explicitly_convertible(From, To);
template<auto From, auto To>
concept QuantitySpecCastableTo = // exposition only
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> && castable(From, To);
template<typename T, auto QS>
concept QuantitySpecOf =
QuantitySpec<T> && QuantitySpec<decltype(QS)> && QuantitySpecConvertibleTo<T{}, QS> &&
!NestedQuantityKindSpecOf<T{}, QS> &&
(QuantityKindSpec<T> || !NestedQuantityKindSpecOf<QS, T{}>);
template<typename T>
concept QSProperty = (!QuantitySpec<T>); // exposition only
template<QuantitySpec auto... From, QuantitySpec Q>
consteval QuantitySpec auto clone-kind-of(Q q); // exposition only
template<QuantitySpec Q>
consteval auto remove-kind(Q q); // exposition only
template<QuantitySpec QS, Unit U>
requires(!AssociatedUnit<U>) || UnitOf<U, QS{}>
consteval Reference auto make-reference(QS, U u); // exposition only
template<QuantitySpec Lhs, QuantitySpec Rhs>
friend consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs);
template<QuantitySpec Lhs, QuantitySpec Rhs>
friend consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs);
template<QuantitySpec Lhs, QuantitySpec Rhs>
friend consteval bool operator==(Lhs, Rhs);
consteval QuantitySpec auto inverse(QuantitySpec auto q);
template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
requires(Den != 0)
consteval QuantitySpec auto pow(Q q);
consteval QuantitySpec auto sqrt(QuantitySpec auto q);
consteval QuantitySpec auto cbrt(QuantitySpec auto q);
consteval bool implicitly_convertible(QuantitySpec auto from, QuantitySpec auto to);
consteval bool explicitly_convertible(QuantitySpec auto from, QuantitySpec auto to);
consteval bool castable(QuantitySpec auto from, QuantitySpec auto to);
consteval bool interconvertible(QuantitySpec auto qs1, QuantitySpec auto qs2);
template<QuantitySpec Q>
consteval QuantitySpec auto get-kind-tree-root(Q q); // exposition only
template<QuantitySpec Q>
consteval QuantityKindSpec auto get_kind(Q);
consteval QuantitySpec auto get_common_quantity_spec(QuantitySpec auto... qs)
requires see below;
template<QuantitySpec auto A, QuantitySpec auto B>
consteval auto get-common-base(); // exposition only
template<QuantitySpec Child, QuantitySpec Parent>
consteval bool is-child-of(Child ch, Parent p); // exposition only
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
template<typename T>
concept Reference = AssociatedUnit<T> || (is-specialization-of<T, reference>());
template<typename T, auto QS>
concept ReferenceOf = Reference<T> && QuantitySpecOf<decltype(get_quantity_spec(T{})), QS>;
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires(!OffsetUnit<decltype(get_unit(R{}))>)
constexpr quantity<R{}, Rep> operator*(FwdRep&& lhs, R r);
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires(!OffsetUnit<decltype(get_unit(R{}))>)
constexpr Quantity auto operator/(FwdRep&& lhs, R);
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{})>
constexpr auto operator*(R, Rep&&) = delete;
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{})>
constexpr auto operator/(R, Rep&&) = delete;
template<Reference R, typename Q>
requires Quantity<std::remove_cvref_t<Q>>
constexpr auto operator*(R, Q&&) = delete;
template<Reference R, typename Q>
requires Quantity<std::remove_cvref_t<Q>>
constexpr auto operator/(R, Q&&) = delete;
template<typename Q2, typename U2>
friend consteval bool operator==(reference, reference<Q2, U2>);
template<AssociatedUnit U2>
friend consteval bool operator==(reference, U2 u2);
template<typename Q2, typename U2>
friend consteval bool convertible(reference, reference<Q2, U2>);
template<AssociatedUnit U2>
friend consteval bool convertible(reference, U2 u2);
template<AssociatedUnit U1>
friend consteval bool convertible(U1 u1, reference);
template<typename Q, typename U>
consteval QuantitySpec auto get_quantity_spec(reference<Q, U>);
consteval AssociatedUnit auto get_common_reference(AssociatedUnit auto u1,
AssociatedUnit auto u2,
AssociatedUnit auto... rest)
requires see below;