fix: add quantity_point::origin, like std::chrono::time_point::clock

This commit is contained in:
Johel Ernesto Guerrero Peña
2021-06-29 20:44:27 +02:00
committed by Mateusz Pusz
parent 7ed29807a6
commit 80eefec97c
26 changed files with 542 additions and 208 deletions
+35 -17
View File
@@ -24,6 +24,7 @@
#pragma once
// IWYU pragma: begin_exports
#include <units/point_origin.h>
#include <units/quantity.h>
#include <compare>
// IWYU pragma: end_exports
@@ -34,18 +35,32 @@
namespace units {
/**
* @brief A quantity point
* @brief A statically unspecified quantity point origin
*
* An absolute quantity with respect to zero (which represents some origin).
* An origin, unspecified in the type system, from which an absolute quantity is measured from.
*
* @tparam D a dimension of the quantity point (can be either a BaseDimension or a DerivedDimension)
*/
template<Dimension D>
struct dynamic_origin : point_origin<D> {
template<Dimension D2>
using rebind = dynamic_origin<D2>;
};
/**
* @brief A quantity point
*
* An absolute quantity measured from an origin.
*
* @tparam O a type that represents the origin from which the quantity point is measured from
* @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, Representation Rep = double>
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep = double>
class quantity_point {
public:
using quantity_type = quantity<D, U, Rep>;
using origin = O;
using quantity_type = quantity<typename origin::dimension, U, Rep>;
using dimension = typename quantity_type::dimension;
using unit = typename quantity_type::unit;
using rep = typename quantity_type::rep;
@@ -63,13 +78,14 @@ public:
requires std::constructible_from<quantity_type, T>
constexpr explicit quantity_point(T&& t) : q_(std::forward<T>(t)) {}
template<QuantityPoint QP2>
template<QuantityPointOf<origin> QP2>
requires std::convertible_to<typename QP2::quantity_type, quantity_type>
constexpr explicit(false) quantity_point(const QP2& qp) : q_(qp.relative()) {}
template<QuantityPointLike QP>
constexpr explicit quantity_point(const QP& qp)
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))>
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))> &&
equivalent<origin, typename quantity_point_like_traits<QP>::origin>
: q_(quantity_point_like_traits<QP>::relative(qp)) {}
quantity_point& operator=(const quantity_point&) = default;
@@ -141,7 +157,8 @@ public:
{
const auto q = lhs.relative() + rhs;
using q_type = decltype(q);
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
typename q_type::rep>(q);
}
template<Quantity Q>
@@ -157,24 +174,25 @@ public:
{
const auto q = lhs.relative() - rhs;
using q_type = decltype(q);
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
return quantity_point<rebind_point_origin_dimension<origin, typename q_type::dimension>, typename q_type::unit,
typename q_type::rep>(q);
}
template<QuantityPoint QP>
template<QuantityPointOf<origin> QP>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs)
requires requires(quantity_type q) { q - rhs.relative(); }
{
return lhs.relative() - rhs.relative();
}
template<QuantityPoint QP>
template<QuantityPointOf<origin> QP>
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
{
return lhs.relative() <=> rhs.relative();
}
template<QuantityPoint QP>
template<QuantityPointOf<origin> QP>
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
{
@@ -183,24 +201,24 @@ public:
};
template<Representation Rep>
explicit quantity_point(Rep) -> quantity_point<dim_one, one, Rep>;
explicit quantity_point(Rep) -> quantity_point<dynamic_origin<dim_one>, one, Rep>;
template<Quantity Q>
explicit quantity_point(Q) -> quantity_point<typename Q::dimension, typename Q::unit, typename Q::rep>;
explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename Q::dimension>, typename Q::unit, typename Q::rep>;
template<QuantityLike Q>
explicit quantity_point(Q) -> quantity_point<typename quantity_like_traits<Q>::dimension,
explicit quantity_point(Q) -> quantity_point<dynamic_origin<typename quantity_like_traits<Q>::dimension>,
typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
template<QuantityPointLike QP>
explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::dimension,
explicit quantity_point(QP) -> quantity_point<typename quantity_point_like_traits<QP>::origin,
typename quantity_point_like_traits<QP>::unit,
typename quantity_point_like_traits<QP>::rep>;
namespace detail {
template<typename D, typename U, typename Rep>
inline constexpr bool is_quantity_point<quantity_point<D, U, Rep>> = true;
template<typename O, typename U, typename Rep>
inline constexpr bool is_quantity_point<quantity_point<O, U, Rep>> = true;
} // namespace detail