feat: 💥 Representation concept removed

This commit is contained in:
Mateusz Pusz
2025-02-12 18:57:06 +01:00
parent 5963a2eb87
commit 4b1f7cd217
6 changed files with 57 additions and 63 deletions

View File

@ -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> {};

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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>);

View File

@ -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>>);