feat: 💥 RepresentationOf concept now also accepts a QuantitySpec and accepts any representation character for quantity kinds

This commit is contained in:
Mateusz Pusz
2024-11-07 18:39:32 +01:00
parent 75b50b8d2c
commit da50348115
14 changed files with 88 additions and 76 deletions

View File

@@ -148,7 +148,7 @@ As we remember, the `quantity` class template is defined as follows:
```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```

View File

@@ -159,15 +159,28 @@ A `Reference` can either be:
[value of a quantity](../../appendix/glossary.md#quantity-value).
### `RepresentationOf<T, Ch>` { #RepresentationOf }
### `RepresentationOf<T, V>` { #RepresentationOf }
`RepresentationOf` concept is satisfied by all `Representation` types that are of a specified
[quantity character](../../appendix/glossary.md#character) `Ch`.
`RepresentationOf` concept is satisfied:
- if the type of `V` satisfies [`QuantitySpec`](#QuantitySpec):
- by all [`Representation`](#Representation) types when `V` describes
a [quantity kind](../../appendix/glossary.md#kind),
- otherwise, by [`Representation`](#Representation) types that are of
a [quantity character](../../appendix/glossary.md#character) associated with a provided
quantity specification `V`.
- if `V` is of `quantity_character` type:
- by [`Representation`](#Representation) types that are of a provided
[quantity character](../../appendix/glossary.md#character).
A user can declare a custom representation type to be of a specific character by providing the specialization
with `true` for one or more of the following variable templates:
- `is_scalar<T>`
- `is_complex<T>`
- `is_vector<T>`
- `is_tensor<T>`

View File

@@ -316,7 +316,7 @@ This is why a `quantity` class template is defined in the library as:
```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```
@@ -365,7 +365,7 @@ In the **mp-units** library, the quantity point is implemented as:
```cpp
template<Reference auto R,
PointOriginFor<get_quantity_spec(R)> auto PO,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity_point;
```

View File

@@ -20,7 +20,7 @@ In the **mp-units** library, a quantity is represented with the following class
```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity;
```

View File

@@ -96,7 +96,7 @@ origin:
```cpp
template<Reference auto R,
PointOriginFor<get_quantity_spec(R)> auto PO = default_point_origin(R),
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity_point;
```

View File

@@ -39,7 +39,7 @@ namespace mp_units {
template<Reference R>
struct delta_ {
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
[[nodiscard]] constexpr quantity<MP_UNITS_EXPRESSION_WORKAROUND(R{}), Rep> operator()(FwdRep&& lhs) const
{
return quantity{std::forward<FwdRep>(lhs), R{}};
@@ -48,7 +48,7 @@ struct delta_ {
template<Reference R>
struct absolute_ {
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
[[nodiscard]] constexpr quantity_point<MP_UNITS_EXPRESSION_WORKAROUND(R{}), default_point_origin(R{}), Rep>
operator()(FwdRep&& lhs) const
{

View File

@@ -78,14 +78,15 @@ concept QuantityConvertibleTo =
// deduced thus the function is evaluated here and may emit truncating conversion or other warnings)
requires(QFrom q) { sudo_cast<QTo>(q); };
template<quantity_character Ch, typename Func, typename T, typename U>
concept InvokeResultOf = std::regular_invocable<Func, T, U> && RepresentationOf<std::invoke_result_t<Func, T, U>, Ch>;
template<auto QS, typename Func, typename T, typename U>
concept InvokeResultOf = QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && std::regular_invocable<Func, T, U> &&
RepresentationOf<std::invoke_result_t<Func, T, U>, QS>;
template<typename Func, typename Q1, typename Q2,
quantity_character Ch = std::invoke_result_t<Func, std::remove_const_t<decltype(Q1::quantity_spec)>,
std::remove_const_t<decltype(Q2::quantity_spec)>>::character>
concept InvocableQuantities =
Quantity<Q1> && Quantity<Q2> && InvokeResultOf<Ch, Func, typename Q1::rep, typename Q2::rep>;
auto QS = std::invoke_result_t<Func, std::remove_const_t<decltype(Q1::quantity_spec)>,
std::remove_const_t<decltype(Q2::quantity_spec)>>{}>
concept InvocableQuantities = QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && Quantity<Q1> && Quantity<Q2> &&
InvokeResultOf<QS, Func, typename Q1::rep, typename Q2::rep>;
// TODO remove the following when clang diagnostics improve
// https://github.com/llvm/llvm-project/issues/96660
@@ -104,7 +105,7 @@ concept CommonlyInvocableQuantities =
Quantity<Q1> && Quantity<Q2> && HaveCommonReference<Q1::reference, Q2::reference> &&
std::convertible_to<Q1, common_quantity_for<Func, Q1, Q2>> &&
std::convertible_to<Q2, common_quantity_for<Func, Q1, Q2>> &&
InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec).character>;
InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)>;
template<auto R1, auto R2, typename Rep1, typename Rep2>
concept SameValueAs = (equivalent(get_unit(R1), get_unit(R2))) && std::convertible_to<Rep1, Rep2>;
@@ -128,7 +129,7 @@ MP_UNITS_EXPORT_BEGIN
* @tparam R a reference of the quantity providing all information about quantity properties
* @tparam Rep a type to be used to represent values of a quantity
*/
template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep = double>
template<Reference auto R, RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity {
public:
Rep numerical_value_is_an_implementation_detail_; ///< needs to be public for a structural type
@@ -227,14 +228,14 @@ public:
return quantity<detail::make_reference(quantity_spec, ToU{}), Rep>{*this};
}
template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires detail::QuantityConvertibleTo<quantity, quantity<reference, ToRep>>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in() const
{
return quantity<reference, ToRep>{*this};
}
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in(ToU) const
{
@@ -248,14 +249,14 @@ public:
return value_cast<ToU{}>(*this);
}
template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires requires(quantity q) { value_cast<ToRep>(q); }
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in() const
{
return value_cast<ToRep>(*this);
}
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires requires(quantity q) { value_cast<ToU{}, ToRep>(q); }
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in(ToU) const
{
@@ -474,17 +475,15 @@ public:
ret::reference};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs)
{
return lhs + ::mp_units::quantity{rhs};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} + rhs;
@@ -501,17 +500,15 @@ public:
ret::reference};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs)
{
return lhs - ::mp_units::quantity{rhs};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} - rhs;
@@ -530,17 +527,15 @@ public:
ret::reference};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs)
{
return lhs % ::mp_units::quantity{rhs};
}
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
requires(Q::unit == ::mp_units::one) &&
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && detail::InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&>
[[nodiscard]] friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs)
{
return ::mp_units::quantity{lhs} % rhs;
@@ -555,7 +550,7 @@ public:
template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, Rep, const Value&>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::multiplies<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Q& q, const Value& v)
{
return ::mp_units::quantity{q.numerical_value_ref_in(unit) * v, R};
@@ -563,7 +558,7 @@ public:
template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, const Value&, Rep>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::multiplies<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Value& v, const Q& q)
{
return ::mp_units::quantity{v * q.numerical_value_ref_in(unit), R};
@@ -579,7 +574,7 @@ public:
template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, Rep, const Value&>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::divides<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator/(const Q& q, const Value& v)
{
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
@@ -588,7 +583,7 @@ public:
template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, const Value&, Rep>
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec, std::divides<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<inverse(quantity_spec)> auto operator/(const Value& v, const Q& q)
{
return ::mp_units::quantity{v / q.numerical_value_ref_in(unit), ::mp_units::one / R};
@@ -605,7 +600,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, RepresentationOf<quantity_character::scalar> Value>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && std::equality_comparable_with<Rep, Value>
[[nodiscard]] friend constexpr bool operator==(const Q& lhs, const Value& rhs)
{
@@ -623,7 +618,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, RepresentationOf<quantity_character::scalar> Value>
template<std::derived_from<quantity> Q, Representation Value>
requires(Q::unit == ::mp_units::one) && std::three_way_comparable_with<Rep, Value>
[[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const Value& rhs)
{
@@ -650,18 +645,21 @@ template<mp_units::Quantity Q1, mp_units::Quantity Q2>
requires requires {
{ mp_units::get_common_reference(Q1::reference, Q2::reference) } -> mp_units::Reference;
typename std::common_type_t<typename Q1::rep, typename Q2::rep>;
requires mp_units::RepresentationOf<std::common_type_t<typename Q1::rep, typename Q2::rep>,
mp_units::get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)>;
}
struct std::common_type<Q1, Q2> {
using type = mp_units::quantity<mp_units::get_common_reference(Q1::reference, Q2::reference),
std::common_type_t<typename Q1::rep, typename Q2::rep>>;
};
template<mp_units::Quantity Q, mp_units::RepresentationOf<mp_units::quantity_character::scalar> Value>
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
template<mp_units::Quantity Q, mp_units::Representation 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::RepresentationOf<mp_units::quantity_character::scalar> Value>
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
template<mp_units::Quantity Q, mp_units::Representation Value>
requires requires { typename std::common_type<Q, Value>; }
struct std::common_type<Value, Q> : std::common_type<Q, Value> {};

View File

@@ -31,7 +31,7 @@
namespace mp_units {
MP_UNITS_EXPORT template<Reference auto R, RepresentationOf<get_quantity_spec(R).character> Rep>
MP_UNITS_EXPORT template<Reference auto R, RepresentationOf<get_quantity_spec(R)> Rep>
class quantity;
namespace detail {

View File

@@ -172,7 +172,7 @@ template<PointOrigin PO>
* @tparam Rep a type to be used to represent values of a quantity point
*/
MP_UNITS_EXPORT template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO = default_point_origin(R),
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity_point {
public:
// member types and values
@@ -329,14 +329,14 @@ public:
return ::mp_units::quantity_point{quantity_ref_from(point_origin).in(ToU{}), point_origin};
}
template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires detail::QuantityConvertibleTo<quantity_type, quantity<reference, ToRep>>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in() const
{
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in<ToRep>(), point_origin};
}
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
{
@@ -350,14 +350,14 @@ public:
return ::mp_units::quantity_point{quantity_ref_from(point_origin).force_in(ToU{}), point_origin};
}
template<RepresentationOf<quantity_spec.character> ToRep>
template<RepresentationOf<quantity_spec> ToRep>
requires requires(quantity_type q) { value_cast<ToRep>(q); }
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in() const
{
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in<ToRep>(), point_origin};
}
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
requires requires(quantity_type q) { value_cast<ToU{}, ToRep>(q); }
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
{

View File

@@ -76,7 +76,7 @@ MP_UNITS_EXPORT template<typename T, auto QS>
concept PointOriginFor = PointOrigin<T> && QuantitySpecOf<MP_UNITS_REMOVE_CONST(decltype(QS)), T::_quantity_spec_>;
MP_UNITS_EXPORT template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO,
RepresentationOf<get_quantity_spec(R).character> Rep>
RepresentationOf<get_quantity_spec(R)> Rep>
class quantity_point;
namespace detail {

View File

@@ -190,24 +190,21 @@ struct reference {
};
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, Reference R, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>)
[[nodiscard]] constexpr quantity<R{}, Rep> operator*(FwdRep&& lhs, R r)
{
return quantity{std::forward<FwdRep>(lhs), r};
}
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, Reference R, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>)
[[nodiscard]] constexpr quantity<inverse(R{}), Rep> operator/(FwdRep&& lhs, R)
{
return quantity{std::forward<FwdRep>(lhs), inverse(R{})};
}
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, Reference R, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires detail::OffsetUnit<decltype(get_unit(R{}))>
[[deprecated(
"References using offset units (e.g., temperatures) should be constructed with the `delta` or `absolute` "
@@ -217,8 +214,7 @@ operator*(FwdRep&& lhs, R r)
return quantity{std::forward<FwdRep>(lhs), r};
}
template<typename FwdRep, Reference R,
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
template<typename FwdRep, Reference R, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>>
requires detail::OffsetUnit<decltype(get_unit(R{}))>
[[deprecated(
"References using offset units (e.g., temperatures) should be constructed with the `delta` or `absolute` "
@@ -229,7 +225,7 @@ operator/(FwdRep&& lhs, R)
}
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{})>
// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
constexpr auto operator*(R, Rep&&)
#if __cpp_deleted_function
@@ -239,7 +235,7 @@ constexpr auto operator*(R, Rep&&)
#endif
template<Reference R, typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{})>
// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
constexpr auto operator/(R, Rep&&)
#if __cpp_deleted_function

View File

@@ -25,6 +25,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/quantity_spec_concepts.h>
#ifndef MP_UNITS_IN_MODULE_INTERFACE
#ifdef MP_UNITS_IMPORT_STD
@@ -165,7 +166,11 @@ MP_UNITS_EXPORT template<typename T>
concept Representation = detail::ScalarRepresentation<T> || detail::ComplexRepresentation<T> ||
detail::VectorRepresentation<T> || detail::TensorRepresentation<T>;
MP_UNITS_EXPORT template<typename T, quantity_character Ch>
concept RepresentationOf = detail::IsOfCharacter<T, Ch> && Representation<T>;
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>)) ||
(std::same_as<quantity_character, decltype(V)> && detail::IsOfCharacter<T, V>));
} // namespace mp_units

View File

@@ -63,7 +63,7 @@ template<Unit 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>>
requires RepresentationOf<ToRep, Q::quantity_spec.character> && std::constructible_from<ToRep, typename Q::rep>
requires RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep>
[[nodiscard]] constexpr quantity<Q::reference, ToRep> value_cast(FwdQ&& q)
{
return detail::sudo_cast<quantity<Q::reference, ToRep>>(std::forward<FwdQ>(q));
@@ -81,7 +81,7 @@ template<Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<F
* @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>>
requires(convertible(Q::reference, ToU)) && RepresentationOf<ToRep, Q::quantity_spec.character> &&
requires(convertible(Q::reference, ToU)) && RepresentationOf<ToRep, Q::quantity_spec> &&
std::constructible_from<ToRep, typename Q::rep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
{
@@ -89,7 +89,7 @@ template<Unit auto ToU, Representation ToRep, typename FwdQ, Quantity Q = std::r
}
template<Representation ToRep, Unit auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires(convertible(Q::reference, ToU)) && RepresentationOf<ToRep, Q::quantity_spec.character> &&
requires(convertible(Q::reference, ToU)) && RepresentationOf<ToRep, Q::quantity_spec> &&
std::constructible_from<ToRep, typename Q::rep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
{
@@ -148,7 +148,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>>
requires RepresentationOf<ToRep, QP::quantity_spec.character> && std::constructible_from<ToRep, typename QP::rep>
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)
{
return {value_cast<ToRep>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
@@ -167,7 +167,7 @@ template<Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cv
* @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>>
requires(convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec.character> &&
requires(convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec> &&
std::constructible_from<ToRep, typename QP::rep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
{
@@ -177,7 +177,7 @@ template<Unit auto ToU, Representation ToRep, typename FwdQP, QuantityPoint QP =
}
template<Representation ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires(convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec.character> &&
requires(convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec> &&
std::constructible_from<ToRep, typename QP::rep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
{

View File

@@ -319,7 +319,7 @@ static_assert(invalid_getter_with_unit_conversion<quantity>);
///////////////////////////////////////
template<Reference auto R, basic_fixed_string additional_nttp_argument,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
RepresentationOf<get_quantity_spec(R)> Rep = double>
struct child_quantity : quantity<R, Rep> {
using quantity_type = quantity<R, Rep>;
static constexpr auto reference = R;