mirror of
https://github.com/mpusz/mp-units.git
synced 2025-06-25 01:01:33 +02:00
feat: 💥 Representation
concept removed
This commit is contained in:
@ -64,14 +64,22 @@ template<Unit UFrom, Unit UTo>
|
||||
template<typename T>
|
||||
concept IsFloatingPoint = treat_as_floating_point<T>;
|
||||
|
||||
template<typename FromRep, typename ToRep, auto FromUnit = one, auto ToUnit = one>
|
||||
concept ValuePreservingTo = Representation<std::remove_cvref_t<FromRep>> && Representation<ToRep> &&
|
||||
Unit<MP_UNITS_REMOVE_CONST(decltype(FromUnit))> &&
|
||||
template<typename FromRep, typename ToRep, auto FromUnit, auto ToUnit>
|
||||
concept ValuePreservingTo = Unit<MP_UNITS_REMOVE_CONST(decltype(FromUnit))> &&
|
||||
Unit<MP_UNITS_REMOVE_CONST(decltype(ToUnit))> && std::assignable_from<ToRep&, FromRep> &&
|
||||
(IsFloatingPoint<ToRep> || (!IsFloatingPoint<std::remove_cvref_t<FromRep>> &&
|
||||
integral_conversion_factor(FromUnit, ToUnit) &&
|
||||
!overflows_non_zero_values<ToRep>(FromUnit, ToUnit)));
|
||||
|
||||
template<typename FromRep, typename ToRep, auto QS>
|
||||
concept RepresentationValuePreservingTo =
|
||||
QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && RepresentationOf<std::remove_cvref_t<FromRep>, QS> &&
|
||||
ValuePreservingTo<FromRep, ToRep, one, one>;
|
||||
|
||||
template<typename FromRep, typename ToRep>
|
||||
concept ScalarRepresentationValuePreservingTo =
|
||||
ScalarRepresentation<std::remove_cvref_t<FromRep>> && ValuePreservingTo<FromRep, ToRep, one, one>;
|
||||
|
||||
template<typename QFrom, typename QTo>
|
||||
concept QuantityConvertibleTo =
|
||||
Quantity<QFrom> && Quantity<QTo> && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) &&
|
||||
@ -103,7 +111,7 @@ template<typename Func, Quantity Q1, Quantity Q2>
|
||||
using common_quantity_for = quantity<get_common_reference(Q1::reference, Q2::reference),
|
||||
std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
|
||||
|
||||
template<Representation Rep, Unit U1, Unit U2>
|
||||
template<typename Rep, Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval bool overflows_non_zero_common_values(U1 u1, U2 u2)
|
||||
{
|
||||
constexpr Unit auto cu = get_common_unit(U1{}, U2{});
|
||||
@ -196,7 +204,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<detail::ValuePreservingTo<Rep> FwdValue>
|
||||
template<detail::RepresentationValuePreservingTo<Rep, quantity_spec> FwdValue>
|
||||
requires detail::ConvertibleWithNumber<reference>
|
||||
constexpr explicit(false) quantity(FwdValue&& val) :
|
||||
numerical_value_is_an_implementation_detail_(std::forward<FwdValue>(val))
|
||||
@ -222,7 +230,7 @@ public:
|
||||
quantity& operator=(const quantity&) = default;
|
||||
quantity& operator=(quantity&&) = default;
|
||||
|
||||
template<detail::ValuePreservingTo<Rep> FwdValue>
|
||||
template<detail::RepresentationValuePreservingTo<Rep, quantity_spec> FwdValue>
|
||||
requires detail::ConvertibleWithNumber<reference>
|
||||
constexpr quantity& operator=(FwdValue&& val)
|
||||
{
|
||||
@ -428,7 +436,7 @@ public:
|
||||
return std::forward<Q>(lhs);
|
||||
}
|
||||
|
||||
template<detail::Mutable<quantity> Q, detail::ValuePreservingTo<Rep> Value>
|
||||
template<detail::Mutable<quantity> Q, detail::ScalarRepresentationValuePreservingTo<Rep> Value>
|
||||
requires(!Quantity<Value>) && requires(rep& a, const Value b) {
|
||||
{ a *= b } -> std::same_as<rep&>;
|
||||
}
|
||||
@ -441,8 +449,8 @@ public:
|
||||
}
|
||||
|
||||
template<detail::Mutable<quantity> Q1, QuantityOf<dimensionless> Q2>
|
||||
requires detail::ConvertibleWithNumber<Q2::reference> && detail::ValuePreservingTo<typename Q2::rep, Rep> &&
|
||||
requires(rep& a, const Q2::rep b) {
|
||||
requires detail::ConvertibleWithNumber<Q2::reference> &&
|
||||
detail::ScalarRepresentationValuePreservingTo<typename Q2::rep, Rep> && requires(rep& a, const Q2::rep b) {
|
||||
{ a *= b } -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator*=(Q1&& lhs, const Q2& rhs)
|
||||
@ -450,7 +458,7 @@ public:
|
||||
return std::forward<Q1>(lhs) *= rhs.numerical_value_is_an_implementation_detail_;
|
||||
}
|
||||
|
||||
template<detail::Mutable<quantity> Q, detail::ValuePreservingTo<Rep> Value>
|
||||
template<detail::Mutable<quantity> Q, detail::ScalarRepresentationValuePreservingTo<Rep> Value>
|
||||
requires(!Quantity<Value>) && requires(rep& a, const Value b) {
|
||||
{ a /= b } -> std::same_as<rep&>;
|
||||
}
|
||||
@ -464,8 +472,8 @@ public:
|
||||
}
|
||||
|
||||
template<detail::Mutable<quantity> Q1, QuantityOf<dimensionless> Q2>
|
||||
requires detail::ConvertibleWithNumber<Q2::reference> && detail::ValuePreservingTo<typename Q2::rep, Rep> &&
|
||||
requires(rep& a, const Q2::rep b) {
|
||||
requires detail::ConvertibleWithNumber<Q2::reference> &&
|
||||
detail::ScalarRepresentationValuePreservingTo<typename Q2::rep, Rep> && requires(rep& a, const Q2::rep b) {
|
||||
{ a /= b } -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator/=(Q1&& lhs, const Q2& rhs)
|
||||
@ -485,7 +493,7 @@ public:
|
||||
ret::reference};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs)
|
||||
@ -493,7 +501,7 @@ public:
|
||||
return lhs + ::mp_units::quantity{rhs};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs)
|
||||
@ -512,7 +520,7 @@ public:
|
||||
ret::reference};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs)
|
||||
@ -520,7 +528,7 @@ public:
|
||||
return lhs - ::mp_units::quantity{rhs};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs)
|
||||
@ -541,7 +549,7 @@ public:
|
||||
ret::reference};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs)
|
||||
@ -549,7 +557,7 @@ public:
|
||||
return lhs % ::mp_units::quantity{rhs};
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> &&
|
||||
detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
|
||||
[[nodiscard]] friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs)
|
||||
@ -617,7 +625,7 @@ public:
|
||||
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> && std::equality_comparable_with<Rep, Value>
|
||||
[[nodiscard]] friend constexpr bool operator==(const Q& lhs, const Value& rhs)
|
||||
{
|
||||
@ -635,7 +643,7 @@ public:
|
||||
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
|
||||
}
|
||||
|
||||
template<std::derived_from<quantity> Q, Representation Value>
|
||||
template<std::derived_from<quantity> Q, RepresentationOf<quantity_spec> Value>
|
||||
requires detail::ConvertibleWithNumber<Q::reference> && std::three_way_comparable_with<Rep, Value>
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const Value& rhs)
|
||||
{
|
||||
@ -644,10 +652,14 @@ public:
|
||||
};
|
||||
|
||||
// CTAD
|
||||
template<Representation Value, Reference R>
|
||||
template<Reference R, RepresentationOf<get_quantity_spec(R{})> Value>
|
||||
quantity(Value v, R) -> quantity<R{}, Value>;
|
||||
|
||||
template<Representation Value>
|
||||
#if MP_UNITS_COMP_GCC == 14
|
||||
template<detail::SomeRepresentation Value>
|
||||
#else
|
||||
template<RepresentationOf<get_quantity_spec(one)> Value>
|
||||
#endif
|
||||
explicit(false) quantity(Value) -> quantity<one, Value>;
|
||||
|
||||
template<QuantityLike Q>
|
||||
@ -672,14 +684,14 @@ struct std::common_type<Q1, Q2> {
|
||||
std::common_type_t<typename Q1::rep, typename Q2::rep>>;
|
||||
};
|
||||
|
||||
template<mp_units::Quantity Q, mp_units::Representation Value>
|
||||
template<mp_units::Quantity Q, mp_units::RepresentationOf<Q::quantity_spec> Value>
|
||||
requires(Q::unit == mp_units::one) &&
|
||||
requires { typename mp_units::quantity<Q::reference, std::common_type_t<typename Q::rep, Value>>; }
|
||||
struct std::common_type<Q, Value> {
|
||||
using type = mp_units::quantity<Q::reference, std::common_type_t<typename Q::rep, Value>>;
|
||||
};
|
||||
|
||||
template<mp_units::Quantity Q, mp_units::Representation Value>
|
||||
template<mp_units::Quantity Q, mp_units::RepresentationOf<Q::quantity_spec> Value>
|
||||
requires requires { typename std::common_type<Q, Value>; }
|
||||
struct std::common_type<Value, Q> : std::common_type<Q, Value> {};
|
||||
|
||||
|
@ -328,27 +328,23 @@ concept VectorRepresentation = NotQuantity<T> && Vector<T> && ScalableByFactor<T
|
||||
// template<typename T>
|
||||
// concept TensorRepresentation = NotQuantity<T> && Tensor<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept Representation =
|
||||
detail::ScalarRepresentation<T> || detail::VectorRepresentation<T>; // || detail::TensorRepresentation<T>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, quantity_character Ch>
|
||||
concept IsOfCharacter =
|
||||
(Ch == quantity_character::real_scalar && RealScalar<T>) ||
|
||||
(Ch == quantity_character::complex_scalar && ComplexScalar<T>) ||
|
||||
(Ch == quantity_character::vector && Vector<T>); // || (Ch == quantity_character::tensor && Tensor<T>);
|
||||
concept IsOfCharacter = (Ch == quantity_character::real_scalar && RealScalarRepresentation<T>) ||
|
||||
(Ch == quantity_character::complex_scalar && ComplexScalarRepresentation<T>) ||
|
||||
(Ch == quantity_character::vector && VectorRepresentation<T>);
|
||||
// || (Ch == quantity_character::tensor && TensorRepresentation<T>);
|
||||
|
||||
template<typename T>
|
||||
concept SomeRepresentation =
|
||||
detail::ScalarRepresentation<T> || detail::VectorRepresentation<T>; // || detail::TensorRepresentation<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
MP_UNITS_EXPORT template<typename T, auto V>
|
||||
concept RepresentationOf =
|
||||
Representation<T> &&
|
||||
((QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(V))> &&
|
||||
(detail::QuantityKindSpec<MP_UNITS_REMOVE_CONST(decltype(V))> || detail::IsOfCharacter<T, V.character>)) ||
|
||||
((detail::QuantityKindSpec<MP_UNITS_REMOVE_CONST(decltype(V))> && detail::SomeRepresentation<T>) ||
|
||||
detail::IsOfCharacter<T, V.character>)) ||
|
||||
(std::same_as<quantity_character, decltype(V)> && detail::IsOfCharacter<T, V>));
|
||||
|
||||
} // namespace mp_units
|
||||
|
@ -37,7 +37,7 @@ namespace mp_units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<Representation Rep, Unit UFrom, Unit UTo>
|
||||
template<typename Rep, Unit UFrom, Unit UTo>
|
||||
[[nodiscard]] consteval bool overflows_non_zero_values(UFrom from, UTo to)
|
||||
{
|
||||
if constexpr (is_same_v<UFrom, UTo> || treat_as_floating_point<Rep>)
|
||||
@ -87,7 +87,7 @@ template<auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity
|
||||
*/
|
||||
template<Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
template<typename ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep>
|
||||
[[nodiscard]] constexpr quantity<Q::reference, ToRep> value_cast(FwdQ&& q)
|
||||
{
|
||||
@ -105,7 +105,7 @@ template<Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<F
|
||||
* @tparam ToU a unit to use for the target quantity
|
||||
* @tparam ToRep a representation type to use for the target quantity
|
||||
*/
|
||||
template<Unit auto ToU, Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
template<Unit auto ToU, typename ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires detail::UnitCompatibleWith<MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::unit, Q::quantity_spec> &&
|
||||
(!detail::overflows_non_zero_values<ToRep>(Q::unit, ToU)) &&
|
||||
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep>
|
||||
@ -114,7 +114,7 @@ template<Unit auto ToU, Representation ToRep, typename FwdQ, Quantity Q = std::r
|
||||
return detail::sudo_cast<quantity<detail::make_reference(Q::quantity_spec, ToU), ToRep>>(std::forward<FwdQ>(q));
|
||||
}
|
||||
|
||||
template<Representation ToRep, Unit auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
template<typename ToRep, Unit auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires detail::UnitCompatibleWith<MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::unit, Q::quantity_spec> &&
|
||||
(!detail::overflows_non_zero_values<ToRep>(Q::unit, ToU)) &&
|
||||
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep>
|
||||
@ -176,7 +176,7 @@ template<Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<F
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity point
|
||||
*/
|
||||
template<Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
template<typename ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep>
|
||||
[[nodiscard]] constexpr quantity_point<QP::reference, QP::point_origin, ToRep> value_cast(FwdQP&& qp)
|
||||
{
|
||||
@ -195,7 +195,7 @@ template<Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cv
|
||||
* @tparam ToU a unit to use for the target quantity
|
||||
* @tparam ToRep a representation type to use for the target quantity
|
||||
*/
|
||||
template<Unit auto ToU, Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
template<Unit auto ToU, typename ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires detail::UnitCompatibleWith<MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::unit, QP::quantity_spec> &&
|
||||
(!detail::overflows_non_zero_values<ToRep>(QP::unit, ToU)) &&
|
||||
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep>
|
||||
@ -206,7 +206,7 @@ template<Unit auto ToU, Representation ToRep, typename FwdQP, QuantityPoint QP =
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
template<Representation ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
template<typename ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires detail::UnitCompatibleWith<MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::unit, QP::quantity_spec> &&
|
||||
(!detail::overflows_non_zero_values<ToRep>(QP::unit, ToU)) &&
|
||||
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep>
|
||||
|
@ -318,8 +318,8 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
||||
* @tparam Q Quantity type being the base of the operation
|
||||
* @return Quantity The epsilon value for quantity's representation type
|
||||
*/
|
||||
template<Representation Rep, Reference R>
|
||||
requires requires { std::numeric_limits<Rep>::epsilon(); }
|
||||
template<typename Rep, Reference R>
|
||||
requires RepresentationOf<Rep, get_quantity_spec(R{})> && requires { std::numeric_limits<Rep>::epsilon(); }
|
||||
[[deprecated(
|
||||
"2.5.0: Use `std::numeric_limits<Quantity>::epsilon()` instead")]] [[nodiscard]] constexpr quantity<R{}, Rep>
|
||||
epsilon(R r) noexcept
|
||||
|
@ -315,20 +315,6 @@ static_assert(ReferenceOf<struct one, isq::angular_measure>);
|
||||
static_assert(!ReferenceOf<decltype(dimensionless[one]), isq::rotation>);
|
||||
static_assert(!ReferenceOf<decltype(dimensionless[one]), isq::angular_measure>);
|
||||
|
||||
// Representation
|
||||
static_assert(Representation<int>);
|
||||
static_assert(Representation<double>);
|
||||
static_assert(!Representation<bool>);
|
||||
static_assert(!Representation<std::optional<int>>);
|
||||
#if MP_UNITS_HOSTED
|
||||
static_assert(Representation<std::complex<float>>);
|
||||
static_assert(Representation<std::complex<double>>);
|
||||
static_assert(Representation<std::complex<long double>>);
|
||||
static_assert(Representation<cartesian_vector<double>>);
|
||||
static_assert(!Representation<std::string>);
|
||||
static_assert(!Representation<std::chrono::seconds>);
|
||||
#endif
|
||||
|
||||
// RepresentationOf
|
||||
static_assert(RepresentationOf<int, quantity_character::real_scalar>);
|
||||
static_assert(!RepresentationOf<int, quantity_character::complex_scalar>);
|
||||
|
@ -71,8 +71,8 @@ namespace {
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
static_assert(Representation<min_impl<int>>);
|
||||
static_assert(Representation<min_impl<double>>);
|
||||
static_assert(RepresentationOf<min_impl<int>, quantity_character::real_scalar>);
|
||||
static_assert(RepresentationOf<min_impl<double>, quantity_character::real_scalar>);
|
||||
|
||||
// construction from a value is not allowed
|
||||
static_assert(!std::constructible_from<quantity<si::metre, min_impl<int>>, min_impl<int>>);
|
||||
|
Reference in New Issue
Block a user