forked from mpusz/mp-units
refactor: 💥 basic_concepts, quantity and quantity_cast refactored
BREAKING CHANGE: ScalableNumber renamed to QuantityValue Resolves #107
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <units/bits/external/downcasting.h>
|
||||
#include <units/bits/external/fixed_string.h>
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <units/customization_points.h>
|
||||
#include <units/ratio.h>
|
||||
#include <units/bits/external/type_traits.h>
|
||||
#include <functional>
|
||||
@@ -229,6 +230,34 @@ template<typename T>
|
||||
concept QuantityPoint = detail::is_quantity_point<T>;
|
||||
|
||||
|
||||
// QuantityValue
|
||||
|
||||
template<typename T, typename U>
|
||||
concept common_type_with_ =
|
||||
std::same_as<std::common_type_t<T, U>, std::common_type_t<U, T>> &&
|
||||
std::constructible_from<std::common_type_t<T, U>, T> &&
|
||||
std::constructible_from<std::common_type_t<T, U>, U>;
|
||||
|
||||
template<typename T, typename U = T>
|
||||
concept scalable_number_ = // exposition only
|
||||
std::regular_invocable<std::multiplies<>, T, U> &&
|
||||
std::regular_invocable<std::divides<>, T, U>;
|
||||
|
||||
template<typename T>
|
||||
concept castable_number_ = // exposition only
|
||||
common_type_with_<T, std::intmax_t> &&
|
||||
scalable_number_<std::common_type_t<T, std::intmax_t>>;
|
||||
|
||||
template<typename T>
|
||||
concept scalable_ = // exposition only
|
||||
castable_number_<T> ||
|
||||
(requires { typename T::value_type; } && castable_number_<typename T::value_type> && scalable_number_<T, std::common_type_t<typename T::value_type, std::intmax_t>>);
|
||||
|
||||
template<typename From, typename To>
|
||||
concept scalable_with_ = // exposition only
|
||||
common_type_with_<From, To> &&
|
||||
scalable_<std::common_type_t<From, To>>;
|
||||
|
||||
// WrappedQuantity
|
||||
namespace detail {
|
||||
|
||||
@@ -248,31 +277,8 @@ inline constexpr bool is_wrapped_quantity<T> = Quantity<typename T::value_type>
|
||||
* recursively (i.e. `std::optional<si::length<si::metre>>`).
|
||||
*/
|
||||
template<typename T>
|
||||
concept WrappedQuantity = detail::is_wrapped_quantity<T>;
|
||||
|
||||
// ScalableNumber
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
concept constructible_from_integral =
|
||||
// construction from an integral type
|
||||
std::constructible_from<T, std::int64_t> &&
|
||||
// unit scaling
|
||||
std::regular_invocable<std::multiplies<>, T, T> &&
|
||||
std::regular_invocable<std::divides<>, T, T>;
|
||||
|
||||
template<typename T>
|
||||
concept not_constructible_from_integral =
|
||||
// not construction from an integral type
|
||||
(!std::constructible_from<T, std::int64_t>) &&
|
||||
|
||||
// scaling by the value from ratio
|
||||
std::regular_invocable<std::multiplies<>, T, std::int64_t> &&
|
||||
std::regular_invocable<std::multiplies<>, std::int64_t, T>; // &&
|
||||
// std::regular_invocable<std::divides<>, T, std::int64_t>; // TODO Uncomment when a bug in LA is fixed
|
||||
|
||||
} // namespace detail
|
||||
concept wrapped_quantity_ = // exposition only
|
||||
detail::is_wrapped_quantity<T>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching non-Quantity types.
|
||||
@@ -280,10 +286,10 @@ concept not_constructible_from_integral =
|
||||
* Satisfied by types that satisfy `(!Quantity<T>) && (!WrappedQuantity<T>) && std::regular<T>`.
|
||||
*/
|
||||
template<typename T>
|
||||
concept ScalableNumber =
|
||||
concept QuantityValue =
|
||||
(!Quantity<T>) &&
|
||||
(!WrappedQuantity<T>) &&
|
||||
(!wrapped_quantity_<T>) &&
|
||||
std::regular<T> &&
|
||||
(detail::constructible_from_integral<T> || detail::not_constructible_from_integral<T>);
|
||||
scalable_<T>;
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep>
|
||||
class quantity_point;
|
||||
|
||||
namespace detail {
|
||||
@@ -70,8 +70,7 @@ quantity_point<D, U, Rep> common_quantity_point_impl(quantity<D, U, Rep>);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<Quantity Q1, Quantity Q2, ScalableNumber Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
||||
requires equivalent<typename Q1::dimension, typename Q2::dimension>
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2, QuantityValue Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
||||
using common_quantity = TYPENAME detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
||||
|
||||
template<QuantityPoint QP1, QuantityPoint QP2>
|
||||
|
||||
@@ -73,7 +73,10 @@ concept QuantityOfT = Quantity<Q> && DimensionOfT<typename Q::dimension, DimTemp
|
||||
* Satisfied by all quantities with a dimension being the instantiation derived from
|
||||
* the provided dimension type.
|
||||
*/
|
||||
template<typename T, typename Dim>
|
||||
concept QuantityOf = Quantity<T> && Dimension<Dim> && equivalent<typename T::dimension, Dim>;
|
||||
template<typename Q, typename Dim>
|
||||
concept QuantityOf = Quantity<Q> && Dimension<Dim> && equivalent<typename Q::dimension, Dim>;
|
||||
|
||||
template<typename Q1, typename Q2>
|
||||
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/concepts.h>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -37,9 +36,13 @@ namespace units {
|
||||
*
|
||||
* @tparam Rep a representation type for which a type trait is defined
|
||||
*/
|
||||
template<ScalableNumber Rep>
|
||||
template<typename Rep>
|
||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
|
||||
template<typename T>
|
||||
requires requires { typename T::value_type; }
|
||||
inline constexpr bool treat_as_floating_point<T> = treat_as_floating_point<typename T::value_type>;
|
||||
|
||||
/**
|
||||
* @brief A type trait that defines zero, one, min, and max for a representation type
|
||||
*
|
||||
@@ -49,7 +52,7 @@ inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
*
|
||||
* @tparam Rep a representation type for which a type trait is defined
|
||||
*/
|
||||
template<ScalableNumber Rep>
|
||||
template<typename Rep>
|
||||
struct quantity_values {
|
||||
static constexpr Rep zero() noexcept { return Rep(0); }
|
||||
static constexpr Rep one() noexcept { return Rep(1); }
|
||||
|
||||
@@ -48,7 +48,7 @@ struct dim_information : base_dimension<"information", bit> {};
|
||||
template<typename T>
|
||||
concept Information = QuantityOf<T, dim_information>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_information> U, QuantityValue Rep = double>
|
||||
using information = quantity<dim_information, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -41,7 +41,7 @@ struct pebibit_per_second : deduced_unit<pebibit_per_second, dim_bitrate, pebibi
|
||||
template<typename T>
|
||||
concept Bitrate = QuantityOf<T, dim_bitrate>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_bitrate> U, QuantityValue Rep = double>
|
||||
using bitrate = quantity<dim_bitrate, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -35,7 +35,7 @@ struct dim_angle : base_dimension<"A", U> {};
|
||||
template<typename T>
|
||||
concept Angle = QuantityOfT<T, dim_angle>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_angle<>> U, QuantityValue Rep = double>
|
||||
using angle = quantity<dim_angle<>, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -40,7 +40,7 @@ struct dim_one : derived_dimension<dim_one, one> {};
|
||||
template<typename T>
|
||||
concept Dimensionless = QuantityOf<T, dim_one>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_one> U, QuantityValue Rep = double>
|
||||
using dimensionless = quantity<dim_one, U, Rep>;
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -29,35 +29,35 @@
|
||||
namespace units::physical::natural {
|
||||
|
||||
struct dim_length : physical::dim_length<inverted_gigaelectronvolt> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_length> U, QuantityValue Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
struct dim_time : physical::dim_time<inverted_gigaelectronvolt> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_time> U, QuantityValue Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
struct dim_mass : physical::dim_mass<gigaelectronvolt> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_mass> U, QuantityValue Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct dim_speed : physical::dim_speed<dim_speed, one, dim_length, dim_time> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_speed> U, QuantityValue Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, gigaelectronvolt, dim_length, dim_time> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_acceleration> U, QuantityValue Rep = double>
|
||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||
|
||||
struct dim_force : physical::dim_force<dim_force, square_gigaelectronvolt, dim_mass, dim_acceleration> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_force> U, QuantityValue Rep = double>
|
||||
using force = quantity<dim_force, U, Rep>;
|
||||
|
||||
struct dim_momentum : physical::dim_momentum<dim_momentum, gigaelectronvolt, dim_mass, dim_speed> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_momentum> U, QuantityValue Rep = double>
|
||||
using momentum = quantity<dim_momentum, U, Rep>;
|
||||
|
||||
struct dim_energy : physical::dim_energy<dim_energy, gigaelectronvolt, dim_force, dim_length> {};
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_force> U, QuantityValue Rep = double>
|
||||
using energy = quantity<dim_force, U, Rep>;
|
||||
|
||||
// Typical UDLs will not work here as the same units are reused by many quantities.
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace units::physical::natural {
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<one, Rep>(1);
|
||||
|
||||
} // namespace units::physical::natural
|
||||
|
||||
@@ -32,7 +32,7 @@ struct mole : named_unit<mole, "mol", prefix> {};
|
||||
|
||||
struct dim_amount_of_substance : physical::dim_amount_of_substance<mole> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_amount_of_substance> U, QuantityValue Rep = double>
|
||||
using amount_of_substance = quantity<dim_amount_of_substance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -52,7 +52,7 @@ struct yottaampere : prefixed_unit<yottaampere, yotta, ampere> {};
|
||||
|
||||
struct dim_electric_current : physical::dim_electric_current<ampere> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_electric_current> U, QuantityValue Rep = double>
|
||||
using electric_current = quantity<dim_electric_current, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct astronomical_unit : named_scaled_unit<astronomical_unit, "au", no_prefix,
|
||||
|
||||
struct dim_length : physical::dim_length<metre> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_length> U, QuantityValue Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -52,7 +52,7 @@ struct yottacandela : prefixed_unit<yottacandela, yotta, candela> {};
|
||||
|
||||
struct dim_luminous_intensity : physical::dim_luminous_intensity<candela> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_luminous_intensity> U, QuantityValue Rep = double>
|
||||
using luminous_intensity = quantity<dim_luminous_intensity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -76,7 +76,7 @@ struct dalton : named_scaled_unit<dalton, "Da", no_prefix, ratio(16'605'390'666'
|
||||
|
||||
struct dim_mass : physical::dim_mass<kilogram> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_mass> U, QuantityValue Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ struct kelvin : named_unit<kelvin, "K", no_prefix> {};
|
||||
|
||||
struct dim_thermodynamic_temperature : physical::dim_thermodynamic_temperature<kelvin> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_thermodynamic_temperature> U, QuantityValue Rep = double>
|
||||
using thermodynamic_temperature = quantity<dim_thermodynamic_temperature, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -43,7 +43,7 @@ struct day : named_scaled_unit<day, "d", no_prefix, ratio(24), hour> {};
|
||||
|
||||
struct dim_time : physical::dim_time<second> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_time> U, QuantityValue Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ using si::centimetre;
|
||||
|
||||
struct dim_length : physical::dim_length<centimetre> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_length> U, QuantityValue Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ using si::gram;
|
||||
|
||||
struct dim_mass : physical::dim_mass<gram> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_mass> U, QuantityValue Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace units::physical::si::cgs {
|
||||
struct gal : named_unit<gal, "Gal", si::prefix> {};
|
||||
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, gal, dim_length, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_acceleration> U, QuantityValue Rep = double>
|
||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ using si::square_centimetre;
|
||||
|
||||
struct dim_area : physical::dim_area<dim_area, square_centimetre, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_area> U, QuantityValue Rep = double>
|
||||
using area = quantity<dim_area, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct erg : named_unit<erg, "erg", si::prefix> {};
|
||||
|
||||
struct dim_energy : physical::dim_energy<dim_energy, erg, dim_force, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_energy> U, QuantityValue Rep = double>
|
||||
using energy = quantity<dim_energy, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct dyne : named_unit<dyne, "dyn", si::prefix> {};
|
||||
|
||||
struct dim_force : physical::dim_force<dim_force, dyne, dim_mass, dim_acceleration> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_force> U, QuantityValue Rep = double>
|
||||
using force = quantity<dim_force, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct erg_per_second : unit<erg_per_second> {};
|
||||
|
||||
struct dim_power : physical::dim_power<dim_power, erg_per_second, dim_energy, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_power> U, QuantityValue Rep = double>
|
||||
using power = quantity<dim_power, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct barye : named_unit<barye, "Ba", si::prefix> {};
|
||||
|
||||
struct dim_pressure : physical::dim_pressure<dim_pressure, barye, dim_force, dim_area> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_pressure> U, QuantityValue Rep = double>
|
||||
using pressure = quantity<dim_pressure, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si::cgs {
|
||||
struct centimetre_per_second : unit<centimetre_per_second> {};
|
||||
struct dim_speed : physical::dim_speed<dim_speed, centimetre_per_second, dim_length, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_speed> U, QuantityValue Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,31 +32,31 @@
|
||||
|
||||
namespace units::physical::si::si2019 {
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto planck_constant = energy<joule, Rep>(6.62607015e-34) * time<second, Rep>(1);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto reduced_planck_constant = energy<gigaelectronvolt, Rep>(6.582119569e-10) * time<second, Rep>(1);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto elementary_charge = electric_charge<coulomb, Rep>(1.602176634e-19);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto boltzmann_constant = energy<joule, Rep>(1.380649e-23) / temperature<kelvin, Rep>(1);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto avogadro_constant = Rep(6.02214076e23) / substance<mole, Rep>(1);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto speed_of_light = speed<metre_per_second, Rep>(299'792'458);
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto hyperfine_structure_transition_frequency = frequency<hertz, Rep>(9'192'631'770);
|
||||
|
||||
// template<ScalableNumber Rep = double>
|
||||
// template<QuantityValue Rep = double>
|
||||
// inline constexpr auto luminous_efficacy = 683_q_lm / 1_q_W;
|
||||
|
||||
template<ScalableNumber Rep = double>
|
||||
template<QuantityValue Rep = double>
|
||||
inline constexpr auto standard_gravity = acceleration<metre_per_second_sq, Rep>(9.80665);
|
||||
|
||||
} // namespace units::physical::si::si2019
|
||||
|
||||
@@ -53,7 +53,7 @@ struct yottagray : prefixed_unit<yottagray, yotta, gray> {};
|
||||
|
||||
struct dim_absorbed_dose : physical::dim_absorbed_dose<dim_absorbed_dose, gray, dim_energy, dim_mass> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_absorbed_dose> U, QuantityValue Rep = double>
|
||||
using absorbed_dose = quantity<dim_absorbed_dose, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace units::physical::si {
|
||||
struct metre_per_second_sq : unit<metre_per_second_sq> {};
|
||||
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, metre_per_second_sq, dim_length, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_acceleration> U, QuantityValue Rep = double>
|
||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct radian_per_second : named_unit<radian_per_second, basic_symbol_text{"ω",
|
||||
|
||||
struct dim_angular_velocity : physical::dim_angular_velocity<dim_angular_velocity, radian_per_second, dim_angle<>, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_angular_velocity> U, QuantityValue Rep = double>
|
||||
using angular_velocity = quantity<dim_angular_velocity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct square_yottametre : deduced_unit<square_yottametre, dim_area, yottametre>
|
||||
|
||||
struct hectare : alias_unit<square_hectometre, "ha", no_prefix> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_area> U, QuantityValue Rep = double>
|
||||
using area = quantity<dim_area, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct yottafarad : prefixed_unit<yottafarad, yotta, farad> {};
|
||||
|
||||
struct dim_capacitance : physical::dim_capacitance<dim_capacitance, farad, dim_electric_charge, dim_voltage> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_capacitance> U, QuantityValue Rep = double>
|
||||
using capacitance = quantity<dim_capacitance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -56,7 +56,7 @@ struct enzyme_unit : named_scaled_unit<enzyme_unit, "U", prefix, ratio(1, 60, -6
|
||||
|
||||
struct dim_catalytic_activity : physical::dim_catalytic_activity<dim_catalytic_activity, katal, dim_time, dim_amount_of_substance> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_catalytic_activity> U, QuantityValue Rep = double>
|
||||
using catalytic_activity = quantity<dim_catalytic_activity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -36,10 +36,10 @@ struct coulomb_per_metre_sq : unit<coulomb_per_metre_sq> {};
|
||||
struct dim_charge_density : physical::dim_charge_density<dim_charge_density, coulomb_per_metre_cub, dim_electric_charge, dim_length> {};
|
||||
struct dim_surface_charge_density : physical::dim_surface_charge_density<dim_surface_charge_density, coulomb_per_metre_sq, dim_electric_charge, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_charge_density> U, QuantityValue Rep = double>
|
||||
using charge_density = quantity<dim_charge_density, U, Rep>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_surface_charge_density> U, QuantityValue Rep = double>
|
||||
using surface_charge_density = quantity<dim_surface_charge_density, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si {
|
||||
struct mol_per_metre_cub : unit<mol_per_metre_cub> {};
|
||||
struct dim_concentration : physical::dim_concentration<dim_concentration, mol_per_metre_cub, dim_amount_of_substance, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_concentration> U, QuantityValue Rep = double>
|
||||
using concentration = quantity<dim_concentration, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -49,7 +49,7 @@ struct yottasiemens : prefixed_unit<yottasiemens, yotta, siemens> {};
|
||||
|
||||
struct dim_conductance : physical::dim_conductance<dim_conductance, siemens, dim_resistance> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_conductance> U, QuantityValue Rep = double>
|
||||
using conductance = quantity<dim_conductance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct ampere_per_metre_sq : unit<ampere_per_metre_sq> {};
|
||||
|
||||
struct dim_current_density : physical::dim_current_density<dim_current_density, ampere_per_metre_sq, dim_electric_current, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_current_density> U, QuantityValue Rep = double>
|
||||
using current_density = quantity<dim_current_density, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct kilogram_per_metre_cub : unit<kilogram_per_metre_cub> {};
|
||||
|
||||
struct dim_density : physical::dim_density<dim_density, kilogram_per_metre_cub, dim_mass, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_density> U, QuantityValue Rep = double>
|
||||
using density = quantity<dim_density, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si {
|
||||
struct pascal_second : unit<pascal_second> {};
|
||||
struct dim_dynamic_viscosity : physical::dim_dynamic_viscosity<dim_dynamic_viscosity, pascal_second, dim_pressure, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_dynamic_viscosity> U, QuantityValue Rep = double>
|
||||
using dynamic_viscosity = quantity<dim_dynamic_viscosity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct coulomb : named_unit<coulomb, "C", prefix> {};
|
||||
|
||||
struct dim_electric_charge : physical::dim_electric_charge<dim_electric_charge, coulomb, dim_time, dim_electric_current> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_electric_charge> U, QuantityValue Rep = double>
|
||||
using electric_charge = quantity<dim_electric_charge, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace units::physical::si {
|
||||
struct volt_per_metre : unit<volt_per_metre> {};
|
||||
struct dim_electric_field_strength : physical::dim_electric_field_strength<dim_electric_field_strength, volt_per_metre, dim_voltage, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_electric_field_strength> U, QuantityValue Rep = double>
|
||||
using electric_field_strength = quantity<dim_electric_field_strength, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -52,7 +52,7 @@ struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, giga, electronvolt> {}
|
||||
|
||||
struct dim_energy : physical::dim_energy<dim_energy, joule, dim_force, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_energy> U, QuantityValue Rep = double>
|
||||
using energy = quantity<dim_energy, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct yottanewton : prefixed_unit<yottanewton, yotta, newton> {};
|
||||
|
||||
struct dim_force : physical::dim_force<dim_force, newton, dim_mass, dim_acceleration> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_force> U, QuantityValue Rep = double>
|
||||
using force = quantity<dim_force, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -48,7 +48,7 @@ struct yottahertz : prefixed_unit<yottahertz, yotta, hertz> {};
|
||||
|
||||
struct dim_frequency : physical::dim_frequency<dim_frequency, hertz, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_frequency> U, QuantityValue Rep = double>
|
||||
using frequency = quantity<dim_frequency, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -39,13 +39,13 @@ struct dim_heat_capacity : physical::dim_heat_capacity<dim_heat_capacity, joule_
|
||||
struct dim_specific_heat_capacity : physical::dim_specific_heat_capacity<dim_specific_heat_capacity, joule_per_kilogram_kelvin, dim_heat_capacity, dim_mass> {};
|
||||
struct dim_molar_heat_capacity : physical::dim_molar_heat_capacity<dim_molar_heat_capacity, joule_per_mole_kelvin, dim_heat_capacity, dim_amount_of_substance> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_heat_capacity> U, QuantityValue Rep = double>
|
||||
using heat_capacity = quantity<dim_heat_capacity, U, Rep>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_specific_heat_capacity> U, QuantityValue Rep = double>
|
||||
using specific_heat_capacity = quantity<dim_specific_heat_capacity, U, Rep>;
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_molar_heat_capacity> U, QuantityValue Rep = double>
|
||||
using molar_heat_capacity = quantity<dim_molar_heat_capacity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -50,7 +50,7 @@ struct yottahenry : prefixed_unit<yottahenry, yotta, henry> {};
|
||||
|
||||
struct dim_inductance : physical::dim_inductance<dim_inductance, henry, dim_magnetic_flux, dim_electric_current> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_inductance> U, QuantityValue Rep = double>
|
||||
using inductance = quantity<dim_inductance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si {
|
||||
struct candela_per_metre_sq : unit<candela_per_metre_sq> {};
|
||||
struct dim_luminance : physical::dim_luminance<dim_luminance, candela_per_metre_sq, dim_luminous_intensity, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_luminance> U, QuantityValue Rep = double>
|
||||
using luminance = quantity<dim_luminance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -50,7 +50,7 @@ struct yottaweber : prefixed_unit<yottaweber, yotta, weber> {};
|
||||
|
||||
struct dim_magnetic_flux : physical::dim_magnetic_flux<dim_magnetic_flux, weber, dim_magnetic_induction, dim_area> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_magnetic_flux> U, QuantityValue Rep = double>
|
||||
using magnetic_flux = quantity<dim_magnetic_flux, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct gauss : named_scaled_unit<gauss, "G", prefix, ratio(1, 10'000), tesla> {}
|
||||
|
||||
struct dim_magnetic_induction : physical::dim_magnetic_induction<dim_magnetic_induction, tesla, dim_voltage, dim_time, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_magnetic_induction> U, QuantityValue Rep = double>
|
||||
using magnetic_induction = quantity<dim_magnetic_induction, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct joule_per_mole : unit<joule_per_mole> {};
|
||||
|
||||
struct dim_molar_energy : physical::dim_molar_energy<dim_molar_energy, joule_per_mole, dim_energy, dim_amount_of_substance> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_molar_energy> U, QuantityValue Rep = double>
|
||||
using molar_energy = quantity<dim_molar_energy, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si {
|
||||
struct kilogram_metre_per_second : unit<kilogram_metre_per_second> {};
|
||||
struct dim_momentum : physical::dim_momentum<dim_momentum, kilogram_metre_per_second, dim_mass, dim_speed> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_momentum> U, QuantityValue Rep = double>
|
||||
using momentum = quantity<dim_momentum, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct henry_per_metre : unit<henry_per_metre> {};
|
||||
|
||||
struct dim_permeability : physical::dim_permeability<dim_permeability, henry_per_metre, dim_inductance, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_permeability> U, QuantityValue Rep = double>
|
||||
using permeability = quantity<dim_permeability, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct farad_per_metre : unit<farad_per_metre> {};
|
||||
|
||||
struct dim_permittivity : physical::dim_permittivity<dim_permittivity, farad_per_metre, dim_capacitance, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_permittivity> U, QuantityValue Rep = double>
|
||||
using permittivity = quantity<dim_permittivity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -49,7 +49,7 @@ struct yottawatt : prefixed_unit<yottawatt, yotta, watt> {};
|
||||
|
||||
struct dim_power : physical::dim_power<dim_power, watt, dim_energy, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_power> U, QuantityValue Rep = double>
|
||||
using power = quantity<dim_power, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct yottapascal : prefixed_unit<yottapascal, yotta, pascal> {};
|
||||
|
||||
struct dim_pressure : physical::dim_pressure<dim_pressure, pascal, dim_force, dim_area> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_pressure> U, QuantityValue Rep = double>
|
||||
using pressure = quantity<dim_pressure, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -50,7 +50,7 @@ struct yottaohm : prefixed_unit<yottaohm, yotta, ohm> {};
|
||||
|
||||
struct dim_resistance : physical::dim_resistance<dim_resistance, ohm, dim_voltage, dim_electric_current> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_resistance> U, QuantityValue Rep = double>
|
||||
using resistance = quantity<dim_resistance, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct dim_speed : physical::dim_speed<dim_speed, metre_per_second, dim_length,
|
||||
|
||||
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_speed, kilometre, hour> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_speed> U, QuantityValue Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ struct newton_per_metre : unit<newton_per_metre> {};
|
||||
|
||||
struct dim_surface_tension : physical::dim_surface_tension<dim_surface_tension, newton_per_metre, dim_force, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_surface_tension> U, QuantityValue Rep = double>
|
||||
using surface_tension = quantity<dim_surface_tension, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct watt_per_metre_kelvin : unit<watt_per_metre_kelvin> {};
|
||||
|
||||
struct dim_thermal_conductivity : physical::dim_thermal_conductivity<dim_thermal_conductivity, watt_per_metre_kelvin, dim_power, dim_length, dim_thermodynamic_temperature> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_thermal_conductivity> U, QuantityValue Rep = double>
|
||||
using thermal_conductivity = quantity<dim_thermal_conductivity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct newton_metre : named_unit<newton_metre, "Nm", prefix> {};
|
||||
|
||||
struct dim_torque : physical::dim_torque<dim_torque, newton_metre, dim_energy, dim_angle<>> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_torque> U, QuantityValue Rep = double>
|
||||
using torque = quantity<dim_torque, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -54,7 +54,7 @@ struct yottavolt : prefixed_unit<yottavolt, yotta, volt> {};
|
||||
|
||||
struct dim_voltage : physical::dim_voltage<dim_voltage, volt, dim_power, dim_electric_current> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_voltage> U, QuantityValue Rep = double>
|
||||
using voltage = quantity<dim_voltage, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -74,7 +74,7 @@ struct exalitre : prefixed_unit<petalitre, exa, litre> {};
|
||||
struct zettalitre : prefixed_alias_unit<cubic_megametre, zetta, litre> {};
|
||||
struct yottalitre : prefixed_unit<yottalitre, yotta, litre> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_volume> U, QuantityValue Rep = double>
|
||||
using volume = quantity<dim_volume, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -51,7 +51,7 @@ struct nautical_mile : named_scaled_unit<nautical_mile, "mi(naut)", no_prefix, r
|
||||
|
||||
struct dim_length : physical::dim_length<foot> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_length> U, QuantityValue Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ struct pound : named_scaled_unit<pound, "lb", no_prefix, ratio(45'359'237, 100'0
|
||||
|
||||
struct dim_mass : physical::dim_mass<pound> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_mass> U, QuantityValue Rep = double>
|
||||
using mass = quantity<dim_mass, U, Rep>;
|
||||
|
||||
struct grain : named_scaled_unit<grain, "gr", no_prefix, ratio(1, 7000), pound>{};
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace units::physical::si::fps {
|
||||
struct foot_per_second_sq : unit<foot_per_second_sq> {};
|
||||
struct dim_acceleration : physical::dim_acceleration<dim_acceleration, foot_per_second_sq, dim_length, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_acceleration> U, QuantityValue Rep = double>
|
||||
using acceleration = quantity<dim_acceleration, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -32,7 +32,7 @@ struct square_foot : unit<square_foot> {};
|
||||
struct dim_area : physical::dim_area<dim_area, square_foot, dim_length> {};
|
||||
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_area> U, QuantityValue Rep = double>
|
||||
using area = quantity<dim_area, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct pound_per_foot_cub : unit<pound_per_foot_cub> {};
|
||||
|
||||
struct dim_density : physical::dim_density<dim_density, pound_per_foot_cub, dim_mass, dim_length> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_density> U, QuantityValue Rep = double>
|
||||
using density = quantity<dim_density, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -39,7 +39,7 @@ struct foot_pound_force : noble_deduced_unit<foot_pound_force, dim_energy, pound
|
||||
|
||||
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_energy> U, QuantityValue Rep = double>
|
||||
using energy = quantity<dim_energy, U, Rep>;
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ struct kip : alias_unit<kilopound_force, "klbf", no_prefix> {};
|
||||
|
||||
struct dim_force : physical::dim_force<dim_force, poundal, dim_mass, dim_acceleration> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_force> U, QuantityValue Rep = double>
|
||||
using force = quantity<dim_force, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -37,7 +37,7 @@ struct foot_pound_force_per_second : deduced_unit<foot_pound_force_per_second, d
|
||||
|
||||
struct horse_power : named_scaled_unit<horse_power, "hp", no_prefix, ratio(550), foot_pound_force_per_second> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_power> U, QuantityValue Rep = double>
|
||||
using power = quantity<dim_power, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct poundal_per_foot_sq : unit<poundal_per_foot_sq> {};
|
||||
|
||||
struct dim_pressure : physical::dim_pressure<dim_pressure, poundal_per_foot_sq, dim_force, dim_area> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_pressure> U, QuantityValue Rep = double>
|
||||
using pressure = quantity<dim_pressure, U, Rep>;
|
||||
|
||||
struct pound_force_per_foot_sq : named_scaled_unit<pound_force_per_foot_sq, "lbf ft2", si::prefix, ratio(32'174'049, 1'000'000), poundal_per_foot_sq> {};
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace units::physical::si::fps {
|
||||
struct foot_per_second : unit<foot_per_second> {};
|
||||
struct dim_speed : physical::dim_speed<dim_speed, foot_per_second, dim_length, dim_time> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_speed> U, QuantityValue Rep = double>
|
||||
using speed = quantity<dim_speed, U, Rep>;
|
||||
|
||||
struct mile_per_hour : deduced_unit<mile_per_hour, dim_speed, mile, hour>{};
|
||||
|
||||
@@ -33,7 +33,7 @@ struct dim_volume : physical::dim_volume<dim_volume, cubic_foot, dim_length> {};
|
||||
|
||||
struct cubic_yard : deduced_unit<cubic_yard, dim_volume, yard> {};
|
||||
|
||||
template<Unit U, ScalableNumber Rep = double>
|
||||
template<UnitOf<dim_volume> U, QuantityValue Rep = double>
|
||||
using volume = quantity<dim_volume, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
+207
-156
@@ -34,19 +34,52 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
concept floating_point_ = // exposition only
|
||||
(Quantity<T> && treat_as_floating_point<typename T::rep>) ||
|
||||
(!Quantity<T> && treat_as_floating_point<T>);
|
||||
|
||||
template<typename From, typename To>
|
||||
concept safe_convertible = // exposition only
|
||||
concept safe_convertible_to_ = // exposition only
|
||||
!(Quantity<From>) &&
|
||||
!(Quantity<To>) &&
|
||||
std::convertible_to<From, To> &&
|
||||
(treat_as_floating_point<To> || (!treat_as_floating_point<From>));
|
||||
(floating_point_<To> || (!floating_point_<From>));
|
||||
|
||||
template<typename Rep, typename QuantityFrom, typename QuantityTo>
|
||||
concept safe_divisible = // exposition only
|
||||
treat_as_floating_point<Rep> ||
|
||||
is_integral(quantity_ratio(QuantityFrom{}) / quantity_ratio(QuantityTo{}));
|
||||
// QFrom ratio is an exact multiple of QTo
|
||||
template<typename QFrom, typename QTo>
|
||||
concept harmonic_ = // exposition only
|
||||
Quantity<QFrom> &&
|
||||
Quantity<QTo> &&
|
||||
requires(QFrom from, QTo to) { requires is_integral(detail::quantity_ratio(from) / detail::quantity_ratio(to)); };
|
||||
|
||||
} // namespace detail
|
||||
template<typename QFrom, typename QTo>
|
||||
concept safe_castable_to_ = // exposition only
|
||||
Quantity<QFrom> &&
|
||||
QuantityOf<QTo, typename QFrom::dimension> &&
|
||||
scalable_with_<typename QFrom::rep, typename QTo::rep> &&
|
||||
(floating_point_<QTo> || (!floating_point_<QFrom> && harmonic_<QFrom, QTo>));
|
||||
|
||||
template<typename Func, typename T, typename U>
|
||||
concept quantity_value_for_ =
|
||||
std::regular_invocable<Func, T, U> &&
|
||||
QuantityValue<std::invoke_result_t<Func, T, U>>;
|
||||
|
||||
template<typename T, typename Func, typename U, typename V>
|
||||
concept invoke_result_convertible_to_ =
|
||||
QuantityValue<T> &&
|
||||
quantity_value_for_<Func, U, V> &&
|
||||
safe_convertible_to_<T, std::invoke_result_t<Func, U, V>>;
|
||||
|
||||
template<typename Func, typename Q, typename V>
|
||||
concept have_quantity_for_ =
|
||||
Quantity<Q> &&
|
||||
(!Quantity<V>) &&
|
||||
quantity_value_for_<Func, typename Q::rep, V>;
|
||||
|
||||
template<typename Func, Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires quantity_value_for_<Func, typename Q1::rep, typename Q2::rep>
|
||||
using common_quantity_for = common_quantity<Q1, Q2, std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
|
||||
|
||||
/**
|
||||
* @brief A quantity
|
||||
@@ -58,63 +91,69 @@ concept safe_divisible = // exposition only
|
||||
* @tparam U a measurement unit of the quantity
|
||||
* @tparam Rep a type to be used to represent values of a quantity
|
||||
*/
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep = double>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep = double>
|
||||
class quantity {
|
||||
Rep value_;
|
||||
public:
|
||||
// member types
|
||||
using dimension = D;
|
||||
using unit = U;
|
||||
using rep = Rep;
|
||||
|
||||
// static member functions
|
||||
[[nodiscard]] static constexpr quantity zero() noexcept
|
||||
requires requires { quantity_values<rep>::zero(); }
|
||||
{
|
||||
return quantity(quantity_values<rep>::zero());
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity one() noexcept
|
||||
requires requires { quantity_values<rep>::one(); }
|
||||
{
|
||||
return quantity(quantity_values<rep>::one());
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity min() noexcept
|
||||
requires requires { quantity_values<rep>::min(); }
|
||||
{
|
||||
return quantity(quantity_values<rep>::min());
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity max() noexcept
|
||||
requires requires { quantity_values<rep>::max(); }
|
||||
{
|
||||
return quantity(quantity_values<rep>::max());
|
||||
}
|
||||
|
||||
// construction, assignment, destruction
|
||||
quantity() = default;
|
||||
quantity(const quantity&) = default;
|
||||
quantity(quantity&&) = default;
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires detail::safe_convertible<Value, rep>
|
||||
constexpr explicit(!(equivalent<quantity, dimensionless<one, Rep>>)) quantity(const Value& v) : value_{static_cast<rep>(v)} {}
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
explicit(!(equivalent<quantity, dimensionless<::units::one, rep>>)) constexpr quantity(const Value& v) : value_(static_cast<rep>(v)) {}
|
||||
|
||||
template<Quantity Q2>
|
||||
requires equivalent<D, typename Q2::dimension> &&
|
||||
detail::safe_convertible<typename Q2::rep, rep> &&
|
||||
detail::safe_divisible<rep, Q2, quantity>
|
||||
constexpr quantity(const Q2& q) : value_{quantity_cast<quantity>(q).count()} {}
|
||||
template<safe_castable_to_<quantity> Q2>
|
||||
constexpr quantity(const Q2& q) : value_(quantity_cast<quantity>(q).count()) {}
|
||||
|
||||
quantity& operator=(const quantity&) = default;
|
||||
quantity& operator=(quantity&&) = default;
|
||||
|
||||
// data access
|
||||
[[nodiscard]] constexpr rep count() const noexcept { return value_; }
|
||||
|
||||
[[nodiscard]] static constexpr quantity zero() noexcept
|
||||
requires requires { quantity_values<Rep>::zero(); }
|
||||
// member unary operators
|
||||
[[nodiscard]] constexpr quantity operator+() const
|
||||
requires requires(rep v) { { +v } -> std::same_as<rep>; }
|
||||
{
|
||||
return quantity(quantity_values<Rep>::zero());
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity one() noexcept
|
||||
requires requires { quantity_values<Rep>::one(); }
|
||||
{
|
||||
return quantity(quantity_values<Rep>::one());
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity min() noexcept
|
||||
requires requires { quantity_values<Rep>::min(); }
|
||||
{
|
||||
return quantity(quantity_values<Rep>::min());
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr quantity max() noexcept
|
||||
requires requires { quantity_values<Rep>::max(); }
|
||||
{
|
||||
return quantity(quantity_values<Rep>::max());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr quantity operator+() const { return *this; }
|
||||
|
||||
[[nodiscard]] constexpr quantity operator-() const
|
||||
[[nodiscard]] constexpr Quantity auto operator-() const
|
||||
requires std::regular_invocable<std::negate<>, rep>
|
||||
{
|
||||
return quantity(-count());
|
||||
using ret = quantity<D, U, decltype(-count())>;
|
||||
return ret(-count());
|
||||
}
|
||||
|
||||
constexpr quantity& operator++()
|
||||
@@ -143,51 +182,45 @@ public:
|
||||
return quantity(value_--);
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
requires detail::safe_convertible<Rep2, rep>
|
||||
constexpr quantity& operator+=(const quantity<D, U, Rep2>& q)
|
||||
constexpr quantity& operator+=(const quantity& q)
|
||||
requires requires(rep a, rep b) { { a += b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ += q.count();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
requires detail::safe_convertible<Rep2, rep>
|
||||
constexpr quantity& operator-=(const quantity<D, U, Rep2>& q)
|
||||
constexpr quantity& operator-=(const quantity& q)
|
||||
requires requires(rep a, rep b) { { a -= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ -= q.count();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
requires detail::safe_convertible<Rep2, rep>
|
||||
constexpr quantity& operator*=(const Rep2& rhs)
|
||||
constexpr quantity& operator*=(const rep& rhs)
|
||||
requires requires(rep a, rep b) { { a *= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
requires detail::safe_convertible<Rep2, rep>
|
||||
constexpr quantity& operator/=(const Rep2& rhs)
|
||||
constexpr quantity& operator/=(const rep& rhs)
|
||||
requires requires(rep a, rep b) { { a /= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires (!treat_as_floating_point<rep>) &&
|
||||
(!treat_as_floating_point<Value>)
|
||||
constexpr quantity& operator%=(const Value& rhs)
|
||||
requires requires(rep v1, Value v2) { { v1 %= v2 } -> std::same_as<rep&>; }
|
||||
constexpr quantity& operator%=(const rep& rhs)
|
||||
requires (!floating_point_<rep>) &&
|
||||
requires(rep a, rep b) { { a %= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ %= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr quantity& operator%=(const quantity& q)
|
||||
requires (!treat_as_floating_point<rep>) &&
|
||||
requires(rep v1, rep v2) { { v1 %= v2 } -> std::same_as<rep&>; }
|
||||
requires (!floating_point_<rep>) &&
|
||||
requires(rep a, rep b) { { a %= b } -> std::same_as<rep&>; }
|
||||
{
|
||||
value_ %= q.count();
|
||||
return *this;
|
||||
@@ -195,143 +228,88 @@ public:
|
||||
|
||||
// Hidden Friends
|
||||
// Below friend functions are to be found via argument-dependent lookup only
|
||||
|
||||
[[nodiscard]] friend constexpr quantity operator+(const quantity& lhs, const quantity& rhs)
|
||||
requires std::regular_invocable<std::plus<>, Rep, Rep>
|
||||
requires invoke_result_convertible_to_<rep, std::plus<>, rep, rep>
|
||||
{
|
||||
return quantity(lhs.count() + rhs.count());
|
||||
}
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires std::regular_invocable<std::plus<>, Rep, Rep2> && equivalent<D, D2>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
using common_rep = decltype(lhs.count() + rhs.count());
|
||||
using ret = common_quantity<quantity, quantity<D2, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() + ret(rhs).count());
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr quantity operator-(const quantity& lhs, const quantity& rhs)
|
||||
requires std::regular_invocable<std::minus<>, Rep, Rep>
|
||||
requires invoke_result_convertible_to_<rep, std::minus<>, rep, rep>
|
||||
{
|
||||
return quantity(lhs.count() - rhs.count());
|
||||
}
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires std::regular_invocable<std::minus<>, Rep, Rep2> && equivalent<D, D2>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
using common_rep = decltype(lhs.count() - rhs.count());
|
||||
using ret = common_quantity<quantity, quantity<D2, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() - ret(rhs).count());
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires std::regular_invocable<std::multiplies<>, Rep, Value>
|
||||
template<typename Value>
|
||||
requires (!Quantity<Value>) &&
|
||||
invoke_result_convertible_to_<rep, std::multiplies<>, rep, Value>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& q, const Value& v)
|
||||
{
|
||||
using common_rep = decltype(q.count() * v);
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
using ret = quantity<D, U, std::invoke_result_t<std::multiplies<>, rep, Value>>;
|
||||
return ret(q.count() * v);
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires std::regular_invocable<std::multiplies<>, Value, Rep>
|
||||
template<typename Value>
|
||||
requires (!Quantity<Value>) &&
|
||||
invoke_result_convertible_to_<rep, std::multiplies<>, rep, Value>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator*(const Value& v, const quantity& q)
|
||||
{
|
||||
return q * v;
|
||||
}
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires std::regular_invocable<std::multiplies<>, Rep, Rep2>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
using dim = dimension_multiply<D, D2>;
|
||||
using ret_unit = downcast_unit<dim, (U::ratio / dimension_unit<D>::ratio) * (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
||||
using common_rep = decltype(lhs.count() * rhs.count());
|
||||
using ret = quantity<dim, ret_unit, common_rep>;
|
||||
return ret(lhs.count() * rhs.count());
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires std::regular_invocable<std::divides<>, Value, Rep>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator/(const Value& v, const quantity& q)
|
||||
{
|
||||
// Expects(q.count() != zero().count());
|
||||
|
||||
using dim = dim_invert<D>;
|
||||
using ret_unit = downcast_unit<dim, ratio(U::ratio.den, U::ratio.num, -U::ratio.exp)>;
|
||||
using common_rep = decltype(v / q.count());
|
||||
using ret = quantity<dim, ret_unit, common_rep>;
|
||||
return ret(v / q.count());
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires std::regular_invocable<std::divides<>, Rep, Value>
|
||||
template<typename Value>
|
||||
requires (!Quantity<Value>) &&
|
||||
invoke_result_convertible_to_<rep, std::divides<>, rep, Value>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& q, const Value& v)
|
||||
{
|
||||
// Expects(v != zero().count());
|
||||
|
||||
using common_rep = decltype(q.count() / v);
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
using ret = quantity<D, U, std::invoke_result_t<std::divides<>, rep, Value>>;
|
||||
return ret(q.count() / v);
|
||||
}
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires std::regular_invocable<std::divides<>, Rep, Rep2>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
template<typename Value>
|
||||
requires (!Quantity<Value>) &&
|
||||
invoke_result_convertible_to_<rep, std::divides<>, Value, rep>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator/(const Value& v, const quantity& q)
|
||||
{
|
||||
// Expects(rhs.count() != zero().count());
|
||||
|
||||
using common_rep = decltype(lhs.count() / rhs.count());
|
||||
using dim = dimension_divide<D, D2>;
|
||||
using ret_unit = downcast_unit<dim, (U::ratio / dimension_unit<D>::ratio) / (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
||||
using ret = quantity<dim, ret_unit, common_rep>;
|
||||
return ret(lhs.count() / rhs.count());
|
||||
// Expects(q.count() != zero().count());
|
||||
using dim = dim_invert<D>;
|
||||
using ret_unit = downcast_unit<dim, inverse(U::ratio)>;
|
||||
using ret = quantity<dim, ret_unit, std::invoke_result_t<std::divides<>, Value, rep>>;
|
||||
return ret(v / q.count());
|
||||
}
|
||||
|
||||
template<ScalableNumber Value>
|
||||
requires (!treat_as_floating_point<Rep>) &&
|
||||
(!treat_as_floating_point<Value>) &&
|
||||
std::regular_invocable<std::modulus<>, Rep, Value>
|
||||
template<typename Value>
|
||||
requires (!Quantity<Value>) && (!floating_point_<rep>) && (!floating_point_<Value>) &&
|
||||
invoke_result_convertible_to_<rep, std::modulus<>, rep, Value>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& q, const Value& v)
|
||||
{
|
||||
using common_rep = decltype(q.count() % v);
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
using ret = quantity<D, U, std::invoke_result_t<std::modulus<>, rep, Value>>;
|
||||
return ret(q.count() % v);
|
||||
}
|
||||
|
||||
template<typename U2, typename Rep2>
|
||||
requires (!treat_as_floating_point<Rep>) &&
|
||||
(!treat_as_floating_point<Rep2>) &&
|
||||
std::regular_invocable<std::modulus<>, Rep, Rep2>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
[[nodiscard]] friend constexpr quantity operator%(const quantity& lhs, const quantity& rhs)
|
||||
requires (!floating_point_<rep>) &&
|
||||
invoke_result_convertible_to_<rep, std::modulus<>, rep, rep>
|
||||
{
|
||||
using common_rep = decltype(lhs.count() % rhs.count());
|
||||
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() % ret(rhs).count());
|
||||
return quantity(lhs.count() % rhs.count());
|
||||
}
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires equivalent<D, D2> &&
|
||||
std::three_way_comparable_with<Rep, Rep2>
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs)
|
||||
requires std::three_way_comparable<rep>
|
||||
#if COMP_GCC == 10 && COMP_GCC_MINOR >= 2
|
||||
= default;
|
||||
#else
|
||||
{
|
||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||
return cq(lhs).count() <=> cq(rhs).count();
|
||||
return lhs.count() <=> rhs.count();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename D2, typename U2, typename Rep2>
|
||||
requires equivalent<D, D2> &&
|
||||
std::equality_comparable_with<Rep, Rep2>
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||
return cq(lhs).count() == cq(rhs).count();
|
||||
}
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity& rhs) = default;
|
||||
|
||||
template<class CharT, class Traits>
|
||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
||||
requires requires { os << q.count(); }
|
||||
{
|
||||
if(os.width()) {
|
||||
// std::setw() applies to the whole quantity output so it has to be first put into std::string
|
||||
@@ -345,9 +323,82 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<ScalableNumber V>
|
||||
// CTAD
|
||||
template<QuantityValue V>
|
||||
/* implicit */ quantity(V) -> quantity<dim_one, one, V>;
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires quantity_value_for_<std::plus<>, typename Q1::rep, typename Q2::rep>
|
||||
[[nodiscard]] constexpr Quantity auto operator+(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
using ret = common_quantity_for<std::plus<>, Q1, Q2>;
|
||||
return ret(ret(lhs).count() + ret(rhs).count());
|
||||
}
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires quantity_value_for_<std::minus<>, typename Q1::rep, typename Q2::rep>
|
||||
[[nodiscard]] constexpr Quantity auto operator-(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
using ret = common_quantity_for<std::minus<>, Q1, Q2>;
|
||||
return ret(ret(lhs).count() - ret(rhs).count());
|
||||
}
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
requires quantity_value_for_<std::multiplies<>, Rep1, Rep2>
|
||||
[[nodiscard]] constexpr Quantity auto operator*(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
using dim = dimension_multiply<D1, D2>;
|
||||
using unit = downcast_unit<dim, (U1::ratio / dimension_unit<D1>::ratio) * (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
||||
using ret = quantity<dim, unit, std::invoke_result_t<std::multiplies<>, Rep1, Rep2>>;
|
||||
return ret(lhs.count() * rhs.count());
|
||||
}
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
requires quantity_value_for_<std::divides<>, Rep1, Rep2>
|
||||
[[nodiscard]] constexpr Quantity auto operator/(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
{
|
||||
// Expects(rhs.count() != zero().count());
|
||||
using dim = dimension_divide<D1, D2>;
|
||||
using unit = downcast_unit<dim, (U1::ratio / dimension_unit<D1>::ratio) / (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
||||
using ret = quantity<dim, unit, std::invoke_result_t<std::divides<>, Rep1, Rep2>>;
|
||||
return ret(lhs.count() / rhs.count());
|
||||
}
|
||||
|
||||
template<typename D1, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
requires (!floating_point_<Rep1>) && (!floating_point_<Rep2>) &&
|
||||
quantity_value_for_<std::modulus<>, Rep1, Rep2>
|
||||
[[nodiscard]] constexpr Quantity auto operator%(const quantity<D1, U1, Rep1>& lhs, const quantity<dim_one, U2, Rep2>& rhs)
|
||||
{
|
||||
using unit = downcast_unit<D1, U1::ratio * U2::ratio>;
|
||||
using ret = quantity<D1, unit, std::invoke_result_t<std::modulus<>, Rep1, Rep2>>;
|
||||
return ret(lhs.count() % rhs.count());
|
||||
}
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
|
||||
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
|
||||
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
using ret = common_quantity_for<std::modulus<>, Q1, Q2>;
|
||||
return ret(ret(lhs).count() % ret(rhs).count());
|
||||
}
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires std::three_way_comparable_with<typename Q1::rep, typename Q2::rep>
|
||||
[[nodiscard]] constexpr auto operator<=>(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
using cq = common_quantity<Q1, Q2>;
|
||||
return cq(lhs).count() <=> cq(rhs).count();
|
||||
}
|
||||
|
||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||
requires std::equality_comparable_with<typename Q1::rep, typename Q2::rep>
|
||||
[[nodiscard]] constexpr bool operator==(const Q1& lhs, const Q2& rhs)
|
||||
{
|
||||
using cq = common_quantity<Q1, Q2>;
|
||||
return cq(lhs).count() == cq(rhs).count();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename D, typename U, typename Rep>
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep>
|
||||
class quantity_point;
|
||||
|
||||
namespace detail {
|
||||
@@ -55,232 +55,6 @@ constexpr auto quantity_ratio(const quantity<D, U, Rep>&)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// quantity_cast
|
||||
namespace detail {
|
||||
|
||||
template<typename To, ratio CRatio, typename CRep, bool NumIsOne, bool DenIsOne, bool ExpIsZero>
|
||||
struct quantity_cast_impl;
|
||||
|
||||
template<typename To, ratio CRatio, typename CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, true, true> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(q.count()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(detail::ipow10(CRatio.exp))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(detail::ipow10(-CRatio.exp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, false, true> {
|
||||
template<typename Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
(static_cast<CRep>(CRatio.num) /
|
||||
static_cast<CRep>(CRatio.den))));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
|
||||
template<typename Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
(static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp)) *
|
||||
(static_cast<CRep>(CRatio.num) /
|
||||
static_cast<CRep>(CRatio.den)))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
(static_cast<CRep>(CRatio.num) *
|
||||
static_cast<CRep>(detail::ipow10(CRatio.exp)) /
|
||||
static_cast<CRep>(CRatio.den))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
|
||||
(static_cast<CRep>(CRatio.num) /
|
||||
(static_cast<CRep>(CRatio.den) *
|
||||
static_cast<CRep>(detail::ipow10(-CRatio.exp))))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, false, true> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio.den)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * (static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp)) * (CRep{1} / static_cast<CRep>(CRatio.den)))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * (static_cast<CRep>(detail::ipow10(CRatio.exp)) / static_cast<CRep>(CRatio.den))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / (static_cast<CRep>(detail::ipow10(-CRatio.exp)) * static_cast<CRep>(CRatio.den))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, true, true> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * (static_cast<CRep>(CRatio.num) * static_cast<CRep>(detail::fpow10<CRep>(CRatio.exp)))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * (static_cast<CRep>(CRatio.num) * static_cast<CRep>(detail::ipow10(CRatio.exp)))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * (static_cast<CRep>(CRatio.num) / static_cast<CRep>(detail::ipow10(-CRatio.exp)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::fpow10<CRep>(CRatio.exp)));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * detail::ipow10(CRatio.exp)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / detail::ipow10(-CRatio.exp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, false, true> {
|
||||
template<typename Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num / CRatio.den)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
|
||||
template<typename Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (detail::fpow10<CRep>(CRatio.exp) * (CRatio.num / CRatio.den))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num * detail::ipow10(CRatio.exp) / CRatio.den)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count()) * (CRatio.num / (CRatio.den * detail::ipow10(-CRatio.exp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, false, true> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / CRatio.den));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (detail::fpow10<CRep>(CRatio.exp) / CRatio.den)));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (detail::ipow10(CRatio.exp) / CRatio.den)));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() / (detail::ipow10(-CRatio.exp) * CRatio.den)));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, true, true> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename To, ratio CRatio, not_constructible_from_integral CRep>
|
||||
struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
|
||||
template<Quantity Q>
|
||||
static constexpr To cast(const Q& q)
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num * detail::fpow10<CRep>(CRatio.exp))));
|
||||
} else {
|
||||
if constexpr (CRatio.exp > 0) {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num * detail::ipow10(CRatio.exp))));
|
||||
}
|
||||
else {
|
||||
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num / detail::ipow10(-CRatio.exp))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Q1, typename Q2>
|
||||
constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
||||
{
|
||||
@@ -294,6 +68,26 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
struct cast_traits;
|
||||
|
||||
template<typename From, typename To>
|
||||
requires common_type_with_<std::common_type_t<From, To>, std::intmax_t>
|
||||
struct cast_traits<From, To> {
|
||||
using ratio_type = std::common_type_t<std::common_type_t<From, To>, std::intmax_t>;
|
||||
using rep_type = ratio_type;
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
requires (!common_type_with_<std::common_type_t<From, To>, std::intmax_t>) &&
|
||||
scalable_number_<std::common_type_t<From, To>, std::intmax_t> &&
|
||||
requires { typename std::common_type_t<From, To>::value_type; } &&
|
||||
common_type_with_<typename std::common_type_t<From, To>::value_type, std::intmax_t>
|
||||
struct cast_traits<From, To> {
|
||||
using ratio_type = std::common_type_t<typename std::common_type_t<From, To>::value_type, std::intmax_t>;
|
||||
using rep_type = std::common_type_t<From, To>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@@ -308,16 +102,33 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
||||
*
|
||||
* @tparam To a target quantity type to cast to
|
||||
*/
|
||||
template<Quantity To, typename D, typename U, typename Rep>
|
||||
template<Quantity To, typename D, typename U, scalable_with_<typename To::rep> Rep>
|
||||
requires QuantityOf<To, D>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
{
|
||||
using c_ratio = std::integral_constant<ratio, detail::cast_ratio(quantity<D, U, Rep>(), To())>;
|
||||
using c_rep = std::common_type_t<typename To::rep, Rep>;
|
||||
using ret_unit = downcast_unit<typename To::dimension, To::unit::ratio>;
|
||||
using ret = quantity<typename To::dimension, ret_unit, typename To::rep>;
|
||||
using cast = detail::quantity_cast_impl<ret, c_ratio::value, c_rep, c_ratio::value.num == 1, c_ratio::value.den == 1, c_ratio::value.exp == 0>;
|
||||
return cast::cast(q);
|
||||
using traits = detail::cast_traits<Rep, typename To::rep>;
|
||||
using ratio_type = TYPENAME traits::ratio_type;
|
||||
using rep_type = TYPENAME traits::rep_type;
|
||||
constexpr auto c_ratio = detail::cast_ratio(quantity<D, U, Rep>(), To());
|
||||
|
||||
if constexpr (treat_as_floating_point<rep_type>) {
|
||||
return ret(static_cast<TYPENAME To::rep>(static_cast<rep_type>(q.count()) *
|
||||
(static_cast<ratio_type>(c_ratio.num) * detail::fpow10<ratio_type>(c_ratio.exp) / static_cast<ratio_type>(c_ratio.den))));
|
||||
}
|
||||
else {
|
||||
if constexpr (c_ratio.exp > 0) {
|
||||
return ret(static_cast<TYPENAME To::rep>(static_cast<rep_type>(q.count()) *
|
||||
(static_cast<ratio_type>(c_ratio.num) * static_cast<ratio_type>(detail::ipow10(c_ratio.exp))) /
|
||||
static_cast<ratio_type>(c_ratio.den)));
|
||||
}
|
||||
else {
|
||||
return ret(static_cast<TYPENAME To::rep>(static_cast<rep_type>(q.count()) *
|
||||
static_cast<ratio_type>(c_ratio.num) /
|
||||
(static_cast<ratio_type>(c_ratio.den) * static_cast<ratio_type>(detail::ipow10(-c_ratio.exp)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,7 +204,7 @@ template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity
|
||||
*/
|
||||
template<ScalableNumber ToRep, typename D, typename U, typename Rep>
|
||||
template<QuantityValue ToRep, typename D, typename U, scalable_with_<ToRep> Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
{
|
||||
return quantity_cast<quantity<D, U, ToRep>>(q);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace units {
|
||||
* @tparam U a measurement unit of the quantity point
|
||||
* @tparam Rep a type to be used to represent values of a quantity point
|
||||
*/
|
||||
template<Dimension D, UnitOf<D> U, ScalableNumber Rep = double>
|
||||
template<Dimension D, UnitOf<D> U, QuantityValue Rep = double>
|
||||
class quantity_point {
|
||||
public:
|
||||
using quantity_type = quantity<D, U, Rep>;
|
||||
|
||||
Reference in New Issue
Block a user