mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-02 20:04:27 +02:00
refactor: 💥 quantity_point_like_traits
now use numerical value instead of the quantity
Resolves #531
This commit is contained in:
@@ -282,9 +282,9 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
|
|||||||
static constexpr auto reference = si::second;
|
static constexpr auto reference = si::second;
|
||||||
using rep = std::chrono::seconds::rep;
|
using rep = std::chrono::seconds::rep;
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<rep> to_numerical_value(const std::chrono::seconds& q)
|
[[nodiscard]] static constexpr convert_implicitly<rep> to_numerical_value(const std::chrono::seconds& d)
|
||||||
{
|
{
|
||||||
return q.count();
|
return d.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<std::chrono::seconds> from_numerical_value(const rep& v)
|
[[nodiscard]] static constexpr convert_implicitly<std::chrono::seconds> from_numerical_value(const rep& v)
|
||||||
@@ -307,12 +307,11 @@ for which an instantiation of `quantity_point_like_traits` type trait yields a v
|
|||||||
- Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept.
|
- Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept.
|
||||||
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
|
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
|
||||||
in `reference`.
|
in `reference`.
|
||||||
- `to_quantity(T)` static member function returning the `quantity` being the offset of the point
|
- `to_numerical_value(T)` static member function returning a raw value of the quantity being the offset
|
||||||
from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper that enables
|
of the point from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper that
|
||||||
implicit conversion in the latter case.
|
enables implicit conversion in the latter case.
|
||||||
- `from_quantity(quantity<reference, rep>)` static member function returning `T` packed in either
|
- `from_numerical_value(rep)` static member function returning `T` packed in either `convert_explicitly`
|
||||||
`convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in the latter
|
or `convert_implicitly` wrapper that enables implicit conversion in the latter case.
|
||||||
case.
|
|
||||||
|
|
||||||
|
|
||||||
??? abstract "Examples"
|
??? abstract "Examples"
|
||||||
@@ -324,17 +323,17 @@ for which an instantiation of `quantity_point_like_traits` type trait yields a v
|
|||||||
struct mp_units::quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> {
|
struct mp_units::quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> {
|
||||||
using T = std::chrono::time_point<C, std::chrono::seconds>;
|
using T = std::chrono::time_point<C, std::chrono::seconds>;
|
||||||
static constexpr auto reference = si::second;
|
static constexpr auto reference = si::second;
|
||||||
static constexpr struct point_origin final : absolute_point_origin<isq::time> {} point_origin{};
|
static constexpr struct point_origin_ final : absolute_point_origin<isq::time> {} point_origin{};
|
||||||
using rep = std::chrono::seconds::rep;
|
using rep = std::chrono::seconds::rep;
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(const T& qp)
|
[[nodiscard]] static constexpr convert_implicitly<rep> to_numerical_value(const T& tp)
|
||||||
{
|
{
|
||||||
return quantity{qp.time_since_epoch()};
|
return tp.time_since_epoch().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<T> from_quantity(const quantity<reference, rep>& q)
|
[[nodiscard]] static constexpr convert_implicitly<T> from_numerical_value(const rep& v)
|
||||||
{
|
{
|
||||||
return T(q);
|
return T(std::chrono::seconds(v));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -174,10 +174,11 @@ type trait:
|
|||||||
- static data member `point_origin` that specifies the absolute point, which is the beginning of
|
- static data member `point_origin` that specifies the absolute point, which is the beginning of
|
||||||
our measurement scale for our points,
|
our measurement scale for our points,
|
||||||
- `rep` type that specifies the underlying storage type,
|
- `rep` type that specifies the underlying storage type,
|
||||||
- `to_quantity(T)` static member function returning the `quantity` being the offset of the point
|
- `to_numerical_value(T)` static member function returning a raw value of the `quantity` being
|
||||||
from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper,
|
the offset of the point from the origin packed in either `convert_explicitly` or `convert_implicitly`
|
||||||
- `from_quantity(quantity<reference, rep>)` static member function returning `T` packed in either
|
wrapper.
|
||||||
`convert_explicitly` or `convert_implicitly` wrapper.
|
- `from_numerical_value(rep)` static member function returning `T` packed in either `convert_explicitly`
|
||||||
|
or `convert_implicitly` wrapper.
|
||||||
|
|
||||||
For example, for our `Timestamp` type, we could provide the following:
|
For example, for our `Timestamp` type, we could provide the following:
|
||||||
|
|
||||||
@@ -187,16 +188,8 @@ struct mp_units::quantity_point_like_traits<Timestamp> {
|
|||||||
static constexpr auto reference = si::second;
|
static constexpr auto reference = si::second;
|
||||||
static constexpr auto point_origin = default_point_origin(reference);
|
static constexpr auto point_origin = default_point_origin(reference);
|
||||||
using rep = decltype(Timestamp::seconds);
|
using rep = decltype(Timestamp::seconds);
|
||||||
|
static constexpr convert_implicitly<rep> to_numerical_value(Timestamp ts) { return ts.seconds; }
|
||||||
static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(Timestamp ts)
|
static constexpr convert_explicitly<Timestamp> from_numerical_value(rep v) { return Timestamp(v); }
|
||||||
{
|
|
||||||
return ts.seconds * si::second;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr convert_explicitly<Timestamp> from_quantity(quantity<reference, rep> q)
|
|
||||||
{
|
|
||||||
return Timestamp(q.numerical_value_ref_in(si::second));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -174,9 +174,9 @@ struct quantity_like_traits;
|
|||||||
* @brief Provides support for external quantity point-like types
|
* @brief Provides support for external quantity point-like types
|
||||||
*
|
*
|
||||||
* The type trait should provide nested @c reference and @c origin objects,
|
* The type trait should provide nested @c reference and @c origin objects,
|
||||||
* a type alias @c rep, and static member functions @c to_quantity(T) that returns
|
* a type alias @c rep, and static member functions @c to_numerical_value(T) that
|
||||||
* the quantity being the offset of the point from the origin and
|
* returns the raw value of the the quantity being the offset of the point from the
|
||||||
* @c from_quantity(quantity<reference, rep>) that returns @c T form this quantity.
|
* origin and @c from_numerical_value(rep) that returns @c T formed this raw value.
|
||||||
* Both return types should be encapsulated in either @c convert_explicitly or
|
* Both return types should be encapsulated in either @c convert_explicitly or
|
||||||
* @c convert_implicitly to specify if the conversion is allowed to happen implicitly.
|
* @c convert_implicitly to specify if the conversion is allowed to happen implicitly.
|
||||||
*
|
*
|
||||||
|
@@ -201,13 +201,14 @@ public:
|
|||||||
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
|
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
|
||||||
quantity_type>
|
quantity_type>
|
||||||
constexpr explicit(
|
constexpr explicit(
|
||||||
is_specialization_of<decltype(quantity_point_like_traits<QP>::to_quantity(std::declval<QP>())),
|
is_specialization_of<decltype(quantity_point_like_traits<QP>::to_numerical_value(std::declval<QP>())),
|
||||||
convert_explicitly> ||
|
convert_explicitly> ||
|
||||||
!std::convertible_to<
|
!std::convertible_to<
|
||||||
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>, quantity_type>)
|
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>, quantity_type>)
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
||||||
quantity_point(const QP& qp) :
|
quantity_point(const QP& qp) :
|
||||||
quantity_from_origin_is_an_implementation_detail_(quantity_point_like_traits<QP>::to_quantity(qp).value)
|
quantity_from_origin_is_an_implementation_detail_(quantity_point_like_traits<QP>::to_numerical_value(qp).value,
|
||||||
|
get_unit(quantity_point_like_traits<QP>::reference))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,16 +298,20 @@ public:
|
|||||||
typename quantity_point_like_traits<QP>::rep>>
|
typename quantity_point_like_traits<QP>::rep>>
|
||||||
[[nodiscard]] explicit(
|
[[nodiscard]] explicit(
|
||||||
is_specialization_of<
|
is_specialization_of<
|
||||||
decltype(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)),
|
decltype(quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
quantity_from_origin_is_an_implementation_detail_.numerical_value_is_an_implementation_detail_)),
|
||||||
convert_explicitly> ||
|
convert_explicitly> ||
|
||||||
!std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
|
!std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
|
||||||
typename quantity_point_like_traits<QP>::rep>>) constexpr
|
typename quantity_point_like_traits<QP>::rep>>) constexpr
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
||||||
operator QP_() const& noexcept(
|
operator QP_() const& noexcept(
|
||||||
noexcept(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)) &&
|
noexcept(quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
quantity_from_origin_is_an_implementation_detail_.numerical_value_is_an_implementation_detail_)) &&
|
||||||
std::is_nothrow_copy_constructible_v<rep>)
|
std::is_nothrow_copy_constructible_v<rep>)
|
||||||
{
|
{
|
||||||
return quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_).value;
|
return quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
quantity_from_origin_is_an_implementation_detail_.numerical_value_is_an_implementation_detail_)
|
||||||
|
.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>>
|
template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>>
|
||||||
@@ -315,16 +320,19 @@ public:
|
|||||||
typename quantity_point_like_traits<QP>::rep>>
|
typename quantity_point_like_traits<QP>::rep>>
|
||||||
[[nodiscard]] explicit(
|
[[nodiscard]] explicit(
|
||||||
is_specialization_of<
|
is_specialization_of<
|
||||||
decltype(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)),
|
decltype(quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
quantity_from_origin_is_an_implementation_detail_.numerical_value_is_an_implementation_detail_)),
|
||||||
convert_explicitly> ||
|
convert_explicitly> ||
|
||||||
!std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
|
!std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
|
||||||
typename quantity_point_like_traits<QP>::rep>>) constexpr
|
typename quantity_point_like_traits<QP>::rep>>) constexpr
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
||||||
operator QP_() && noexcept(
|
operator QP_() && noexcept(
|
||||||
noexcept(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)) &&
|
noexcept(quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
quantity_from_origin_is_an_implementation_detail_.numerical_value_is_an_implementation_detail_)) &&
|
||||||
std::is_nothrow_move_constructible_v<rep>)
|
std::is_nothrow_move_constructible_v<rep>)
|
||||||
{
|
{
|
||||||
return quantity_point_like_traits<QP>::from_quantity(std::move(quantity_from_origin_is_an_implementation_detail_))
|
return quantity_point_like_traits<QP>::from_numerical_value(
|
||||||
|
std::move(quantity_from_origin_is_an_implementation_detail_).numerical_value_is_an_implementation_detail_)
|
||||||
.value;
|
.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,11 +395,10 @@ template<Quantity Q, PointOriginFor<Q::quantity_spec> PO>
|
|||||||
quantity_point(Q q, PO) -> quantity_point<Q::reference, PO{}, typename Q::rep>;
|
quantity_point(Q q, PO) -> quantity_point<Q::reference, PO{}, typename Q::rep>;
|
||||||
|
|
||||||
template<QuantityPointLike QP>
|
template<QuantityPointLike QP>
|
||||||
explicit(
|
explicit(is_specialization_of<decltype(quantity_point_like_traits<QP>::to_numerical_value(std::declval<QP>())),
|
||||||
is_specialization_of<decltype(quantity_point_like_traits<QP>::to_quantity(std::declval<QP>())), convert_explicitly>)
|
convert_explicitly>) quantity_point(QP)
|
||||||
quantity_point(QP)
|
-> quantity_point<quantity_point_like_traits<QP>::reference, quantity_point_like_traits<QP>::point_origin,
|
||||||
-> quantity_point<quantity_point_like_traits<QP>::reference, quantity_point_like_traits<QP>::point_origin,
|
typename quantity_point_like_traits<QP>::rep>;
|
||||||
typename quantity_point_like_traits<QP>::rep>;
|
|
||||||
|
|
||||||
template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
||||||
// TODO simplify when gcc catches up
|
// TODO simplify when gcc catches up
|
||||||
|
@@ -159,14 +159,12 @@ concept QuantityPointLike = requires {
|
|||||||
typename quantity_point_like_traits<T>::rep;
|
typename quantity_point_like_traits<T>::rep;
|
||||||
requires RepresentationOf<typename quantity_point_like_traits<T>::rep,
|
requires RepresentationOf<typename quantity_point_like_traits<T>::rep,
|
||||||
get_quantity_spec(quantity_point_like_traits<T>::reference).character>;
|
get_quantity_spec(quantity_point_like_traits<T>::reference).character>;
|
||||||
} && requires(T qp, quantity<quantity_point_like_traits<T>::reference, typename quantity_point_like_traits<T>::rep> q) {
|
} && requires(T qp, typename quantity_point_like_traits<T>::rep v) {
|
||||||
{
|
{
|
||||||
quantity_point_like_traits<T>::to_quantity(qp)
|
quantity_point_like_traits<T>::to_numerical_value(qp)
|
||||||
} -> detail::ConversionSpecOf<
|
} -> detail::ConversionSpecOf<typename quantity_point_like_traits<T>::rep>;
|
||||||
quantity<quantity_point_like_traits<T>::reference, typename quantity_point_like_traits<T>::rep>>;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
quantity_point_like_traits<T>::from_quantity(q)
|
quantity_point_like_traits<T>::from_numerical_value(v)
|
||||||
} -> detail::ConversionSpecOf<T>;
|
} -> detail::ConversionSpecOf<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -100,16 +100,16 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
|
|||||||
static constexpr auto point_origin = chrono_point_origin<C>;
|
static constexpr auto point_origin = chrono_point_origin<C>;
|
||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(const T& qp) noexcept(
|
[[nodiscard]] static constexpr convert_implicitly<rep> to_numerical_value(const T& tp) noexcept(
|
||||||
std::is_nothrow_copy_constructible_v<rep>)
|
std::is_nothrow_copy_constructible_v<rep>)
|
||||||
{
|
{
|
||||||
return quantity{qp.time_since_epoch()};
|
return tp.time_since_epoch().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static constexpr convert_implicitly<T> from_quantity(const quantity<reference, rep>& q) noexcept(
|
[[nodiscard]] static constexpr convert_implicitly<T> from_numerical_value(const rep& v) noexcept(
|
||||||
std::is_nothrow_copy_constructible_v<rep>)
|
std::is_nothrow_copy_constructible_v<rep>)
|
||||||
{
|
{
|
||||||
return T(q);
|
return T(std::chrono::duration<Rep, Period>(v));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user