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