template<typename T>
struct actual-value-type : cond-value-type<T> {}; // see N4971, [readable.traits]
template<typename T>
requires(!std::is_pointer_v<T> && !std::is_array_v<T>) &&
requires { typename std::indirectly_readable_traits<T>::value_type; }
struct actual-value-type<T> : std::indirectly_readable_traits<T> {};
template<typename T>
using actual-value-type-t = actual-value-type<T>::value_type;
template<typename Rep>
constexpr bool treat_as_floating_point =
std::chrono::treat_as_floating_point_v<actual-value-type-t<Rep>>;
template<typename T>
constexpr bool disable_scalar = false;
template<typename T>
constexpr bool disable_complex = false;
template<typename T>
constexpr bool disable_vector = false;
static constexpr Rep one() noexcept;
template<typename T>
concept WeaklyRegular = std::copyable<T> && std::equality_comparable<T>; // exposition only
template<typename T>
concept Scalar = (!disable_scalar<T>) && WeaklyRegular<T> && requires(T a, T b) { // exposition only
// scalar operations
{ -a } -> std::common_with<T>;
{ a + b } -> std::common_with<T>;
{ a - b } -> std::common_with<T>;
{ a * b } -> std::common_with<T>;
{ a / b } -> std::common_with<T>;
};
template<typename T>
using value-type-t = actual-value-type-t<T>; // exposition only, see [qty.fp.traits]
template<typename T>
concept Complex = // exposition only
(!disable_complex<T>) && WeaklyRegular<T> && Scalar<value-type-t<T>> &&
std::constructible_from<T, value-type-t<T>, value-type-t<T>> &&
requires(T a, T b, value-type-t<T> s) {
// complex operations
{ -a } -> std::common_with<T>;
{ a + b } -> std::common_with<T>;
{ a - b } -> std::common_with<T>;
{ a * b } -> std::common_with<T>;
{ a / b } -> std::common_with<T>;
{ a * s } -> std::common_with<T>;
{ s * a } -> std::common_with<T>;
{ a / s } -> std::common_with<T>;
::mp_units::real(a);
::mp_units::imag(a);
::mp_units::modulus(a);
};
template<typename T>
concept Vector = // exposition only
(!disable_vector<T>) && WeaklyRegular<T> && Scalar<value-type-t<T>> &&
requires(T a, T b, value-type-t<T> s) {
// vector operations
{ -a } -> std::common_with<T>;
{ a + b } -> std::common_with<T>;
{ a - b } -> std::common_with<T>;
{ a * s } -> std::common_with<T>;
{ s * a } -> std::common_with<T>;
{ a / s } -> std::common_with<T>;
::mp_units::magnitude(a);
};
template<typename T>
using scaling-factor-type-t = // exposition only
std::conditional_t<treat_as_floating_point<T>, long double, std::intmax_t>;
template<typename T>
concept ScalarRepresentation = // exposition only
(!is-specialization-of<T, quantity>()) && Scalar<T> &&
requires(T a, T b, scaling-factor-type-t<T> f) {
// scaling
{ a * f } -> std::common_with<T>;
{ f * a } -> std::common_with<T>;
{ a / f } -> std::common_with<T>;
};
template<typename T>
concept ComplexRepresentation = // exposition only
(!is-specialization-of<T, quantity>()) && Complex<T> &&
requires(T a, T b, scaling-factor-type-t<T> f) {
// scaling
{ a * T(f) } -> std::common_with<T>;
{ T(f) * a } -> std::common_with<T>;
{ a / T(f) } -> std::common_with<T>;
};
template<typename T>
concept Representation = ScalarRepresentation<T> || ComplexRepresentation<T> ||
VectorRepresentation<T>;
template<typename T, quantity_character Ch>
concept IsOfCharacter = (Ch == quantity_character::real_scalar && Scalar<T>) || // exposition only
(Ch == quantity_character::complex_scalar && Complex<T>) ||
(Ch == quantity_character::vector && Vector<T>);
template<typename T, auto V>
concept RepresentationOf =
Representation<T> && ((QuantitySpec<decltype(V)> &&
(QuantityKindSpec<decltype(V)> || IsOfCharacter<T, V.character>)) ||
(std::same_as<quantity_character, decltype(V)> && IsOfCharacter<T, V>));