forked from mpusz/mp-units
fix: add quantity_point::origin, like std::chrono::time_point::clock
This commit is contained in:
committed by
Mateusz Pusz
parent
7ed29807a6
commit
80eefec97c
@@ -205,6 +205,52 @@ concept UnitOf =
|
||||
Dimension<D> &&
|
||||
std::same_as<typename U::reference, typename dimension_unit<D>::reference>;
|
||||
|
||||
// PointOrigin
|
||||
|
||||
template<Dimension D>
|
||||
struct point_origin;
|
||||
|
||||
/**
|
||||
* @brief A concept matching a point origin
|
||||
*
|
||||
* Satisfied by types derived from an specialization of @c point_origin.
|
||||
*/
|
||||
template<typename T>
|
||||
concept PointOrigin = is_derived_from_specialization_of<T, point_origin> &&
|
||||
requires {
|
||||
typename T::dimension;
|
||||
requires Dimension<typename T::dimension>;
|
||||
typename T::point_origin;
|
||||
requires std::same_as<typename T::point_origin, point_origin<typename T::dimension>>;
|
||||
requires !std::same_as<T, point_origin<typename T::dimension>>;
|
||||
};
|
||||
|
||||
// RebindablePointOriginFor
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename O, typename D>
|
||||
struct rebind_point_origin_dimension_impl {
|
||||
using type = typename O::template rebind<D>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<PointOrigin O, Dimension D>
|
||||
using rebind_point_origin_dimension = typename conditional<is_same_v<typename O::dimension, D>, std::type_identity<O>,
|
||||
detail::rebind_point_origin_dimension_impl<O, D>>::type;
|
||||
|
||||
/**
|
||||
* @brief A concept predicating the possibility of changing an origin's dimension
|
||||
*
|
||||
* Satisfied by point origins whose dimension can be made to be `D`.
|
||||
*/
|
||||
template<typename T, typename D>
|
||||
concept RebindablePointOriginFor =
|
||||
requires { typename rebind_point_origin_dimension<T, D>; } &&
|
||||
PointOrigin<rebind_point_origin_dimension<T, D>> &&
|
||||
std::same_as<D, typename rebind_point_origin_dimension<T, D>::dimension>;
|
||||
|
||||
// Kind
|
||||
namespace detail {
|
||||
|
||||
@@ -216,7 +262,7 @@ struct _kind_base;
|
||||
template<typename T, template<typename...> typename Base>
|
||||
concept kind_impl_ =
|
||||
is_derived_from_specialization_of<T, Base> &&
|
||||
requires(T* t) {
|
||||
requires {
|
||||
typename T::base_kind;
|
||||
typename T::dimension;
|
||||
requires Dimension<typename T::dimension>;
|
||||
@@ -236,7 +282,7 @@ concept Kind =
|
||||
// PointKind
|
||||
namespace detail {
|
||||
|
||||
template<Kind>
|
||||
template<Kind, PointOrigin>
|
||||
struct _point_kind_base;
|
||||
|
||||
} // namespace detail
|
||||
@@ -247,7 +293,12 @@ struct _point_kind_base;
|
||||
* Satisfied by all point kind types derived from an specialization of @c point_kind.
|
||||
*/
|
||||
template<typename T>
|
||||
concept PointKind = kind_impl_<T, detail::_point_kind_base>;
|
||||
concept PointKind =
|
||||
kind_impl_<T, detail::_point_kind_base> &&
|
||||
requires { typename T::origin; } &&
|
||||
PointOrigin<typename T::origin> &&
|
||||
std::same_as<typename T::dimension, typename T::base_kind::dimension> &&
|
||||
std::same_as<typename T::dimension, typename T::origin::dimension>;
|
||||
|
||||
// Reference
|
||||
namespace detail {
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace units {
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||
class quantity_point;
|
||||
|
||||
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
||||
@@ -99,7 +99,8 @@ template<units::QuantityPoint QP1, units::QuantityPointEquivalentTo<QP1> QP2>
|
||||
requires requires { typename common_type_t<typename QP1::rep, typename QP2::rep>; }
|
||||
struct common_type<QP1, QP2> {
|
||||
using type = units::quantity_point<
|
||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension,
|
||||
units::rebind_point_origin_dimension<typename QP1::origin,
|
||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::dimension>,
|
||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::unit,
|
||||
typename common_type_t<typename QP1::quantity_type, typename QP2::quantity_type>::rep>;
|
||||
};
|
||||
|
||||
@@ -81,29 +81,48 @@ template<Unit U1, Dimension D1, Unit U2, Dimension D2>
|
||||
struct equivalent_unit : std::disjunction<equivalent_impl<U1, U2>,
|
||||
std::bool_constant<U1::ratio / dimension_unit<D1>::ratio == U2::ratio / dimension_unit<D2>::ratio>> {};
|
||||
|
||||
// point origins
|
||||
|
||||
template<PointOrigin T, PointOrigin U>
|
||||
struct equivalent_impl<T, U> : std::bool_constant<requires { // TODO: Simplify when Clang catches up.
|
||||
requires RebindablePointOriginFor<T, typename U::dimension> && RebindablePointOriginFor<U, typename T::dimension> &&
|
||||
std::same_as<T, rebind_point_origin_dimension<U, typename T::dimension>> &&
|
||||
std::same_as<U, rebind_point_origin_dimension<T, typename U::dimension>>;
|
||||
} && equivalent_impl<typename T::dimension, typename U::dimension>::value> {};
|
||||
|
||||
|
||||
// (point) kinds
|
||||
|
||||
template<typename T, typename U>
|
||||
requires (Kind<T> && Kind<U>) || (PointKind<T> && PointKind<U>)
|
||||
template<Kind T, Kind U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::conjunction<std::is_same<typename T::base_kind, typename U::base_kind>,
|
||||
equivalent_impl<typename T::dimension, typename U::dimension>> {};
|
||||
|
||||
template<PointKind T, PointKind U>
|
||||
struct equivalent_impl<T, U> :
|
||||
std::conjunction<equivalent_impl<typename T::base_kind, typename U::base_kind>,
|
||||
equivalent_impl<typename T::origin, typename U::origin>> {};
|
||||
|
||||
|
||||
// quantities, quantity points, quantity (point) kinds
|
||||
|
||||
template<typename Q1, typename Q2>
|
||||
requires (Quantity<Q1> && Quantity<Q2>) || (QuantityPoint<Q1> && QuantityPoint<Q2>)
|
||||
template<Quantity Q1, Quantity Q2>
|
||||
struct equivalent_impl<Q1, Q2> : std::conjunction<equivalent_impl<typename Q1::dimension, typename Q2::dimension>,
|
||||
equivalent_unit<typename Q1::unit, typename Q1::dimension,
|
||||
typename Q2::unit, typename Q2::dimension>> {};
|
||||
|
||||
template<typename QK1, typename QK2>
|
||||
requires (QuantityKind<QK1> && QuantityKind<QK2>) || (QuantityPointKind<QK1> && QuantityPointKind<QK2>)
|
||||
template<QuantityPoint QP1, QuantityPoint QP2>
|
||||
struct equivalent_impl<QP1, QP2> : std::conjunction<equivalent_impl<typename QP1::quantity_type, typename QP2::quantity_type>,
|
||||
equivalent_impl<typename QP1::origin, typename QP2::origin>> {};
|
||||
|
||||
template<QuantityKind QK1, QuantityKind QK2>
|
||||
struct equivalent_impl<QK1, QK2> : std::conjunction<equivalent_impl<typename QK1::kind_type, typename QK2::kind_type>,
|
||||
equivalent_impl<typename QK1::quantity_type, typename QK2::quantity_type>> {};
|
||||
|
||||
template<QuantityPointKind QPK1, QuantityPointKind QPK2>
|
||||
struct equivalent_impl<QPK1, QPK2> : std::conjunction<equivalent_impl<typename QPK1::quantity_kind_type, typename QPK2::quantity_kind_type>,
|
||||
equivalent_impl<typename QPK1::origin, typename QPK2::origin>> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, typename U>
|
||||
|
||||
@@ -85,21 +85,20 @@ template<typename Q1, typename Q2>
|
||||
concept QuantityEquivalentTo = Quantity<Q1> && QuantityOf<Q2, typename Q1::dimension>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching all quantity points with provided dimension
|
||||
* @brief A concept matching all quantity points of the provided origin
|
||||
*
|
||||
* Satisfied by all quantity points with a dimension being the instantiation derived from
|
||||
* the provided dimension type.
|
||||
* Satisfied by all quantity points with an origin equivalent to the provided one.
|
||||
*/
|
||||
template<typename QP, typename Dim>
|
||||
concept QuantityPointOf = QuantityPoint<QP> && Dimension<Dim> && equivalent<typename QP::dimension, Dim>;
|
||||
template<typename QP, typename Orig>
|
||||
concept QuantityPointOf = QuantityPoint<QP> && PointOrigin<Orig> && equivalent<typename QP::origin, Orig>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching two equivalent quantity points
|
||||
*
|
||||
* Satisfied by quantity points having equivalent dimensions.
|
||||
* Satisfied by quantity points having equivalent origins.
|
||||
*/
|
||||
template<typename QP1, typename QP2>
|
||||
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::dimension>;
|
||||
concept QuantityPointEquivalentTo = QuantityPoint<QP1> && QuantityPointOf<QP2, typename QP1::origin>;
|
||||
|
||||
/**
|
||||
* @brief A concept matching only quantity kinds of a specific kind.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <units/customization_points.h>
|
||||
// IWYU pragma: begin_exports
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/point_origin.h>
|
||||
#include <chrono>
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
@@ -38,10 +39,13 @@ struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
||||
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct clock_origin : point_origin<isq::si::dim_time> { };
|
||||
|
||||
template<typename C, typename Rep, typename Period>
|
||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||
using dimension = isq::si::dim_time;
|
||||
using unit = downcast_unit<dimension, ratio(Period::num, Period::den)>;
|
||||
using origin = clock_origin<C>;
|
||||
using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
|
||||
using rep = Rep;
|
||||
[[nodiscard]] static constexpr auto relative(
|
||||
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
|
||||
@@ -49,4 +53,11 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename C, typename Rep, typename Period>
|
||||
inline constexpr bool is_quantity_point_like<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -88,7 +88,7 @@ struct quantity_like_traits;
|
||||
/**
|
||||
* @brief Provides support for external quantity point-like types
|
||||
*
|
||||
* The type trait should provide the following nested type aliases: @c dimension, @c unit, @c rep,
|
||||
* The type trait should provide the following nested type aliases: @c origin, @c unit, @c rep,
|
||||
* and a static member function @c relative(T) that will return the quantity-like value of the quantity point.
|
||||
*
|
||||
* Usage example can be found in @c units/chrono.h header file.
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
template<Dimension D>
|
||||
struct dynamic_origin;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename K, Dimension D>
|
||||
@@ -35,10 +38,11 @@ struct _kind_base : downcast_base<_kind_base<K, D>> {
|
||||
using dimension = D;
|
||||
};
|
||||
|
||||
template<Kind K>
|
||||
struct _point_kind_base : downcast_base<_point_kind_base<K>> {
|
||||
template<Kind K, PointOrigin O>
|
||||
struct _point_kind_base : downcast_base<_point_kind_base<K, O>> {
|
||||
using base_kind = K;
|
||||
using dimension = typename K::dimension;
|
||||
using origin = O;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -47,9 +51,9 @@ template<Kind K, Dimension D>
|
||||
requires Kind<downcast<detail::_kind_base<typename K::base_kind, D>>>
|
||||
using downcast_kind = downcast<detail::_kind_base<typename K::base_kind, D>>;
|
||||
|
||||
template<Kind K>
|
||||
requires PointKind<downcast<detail::_point_kind_base<K>>>
|
||||
using downcast_point_kind = downcast<detail::_point_kind_base<K>>;
|
||||
template<Kind K, PointOrigin O = dynamic_origin<typename K::dimension>>
|
||||
requires PointKind<downcast<detail::_point_kind_base<K, O>>>
|
||||
using downcast_point_kind = downcast<detail::_point_kind_base<K, O>>;
|
||||
|
||||
template<typename K, Dimension D>
|
||||
struct kind : downcast_dispatch<K, detail::_kind_base<K, D>> {};
|
||||
@@ -58,7 +62,7 @@ template<typename DK, Dimension D, Kind BK>
|
||||
requires std::same_as<BK, typename BK::base_kind>
|
||||
struct derived_kind : downcast_dispatch<DK, detail::_kind_base<BK, D>> {};
|
||||
|
||||
template<typename DPK, Kind BK>
|
||||
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK>> {};
|
||||
template<typename DPK, Kind BK, PointOrigin O = dynamic_origin<typename BK::dimension>>
|
||||
struct point_kind : downcast_dispatch<DPK, detail::_point_kind_base<BK, O>> {};
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/basic_concepts.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
template<Dimension D>
|
||||
struct point_origin {
|
||||
using dimension = D;
|
||||
};
|
||||
|
||||
} // namespace units
|
||||
@@ -39,7 +39,7 @@ namespace units {
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
class quantity;
|
||||
|
||||
template<Dimension D, UnitOf<D> U, Representation Rep>
|
||||
template<PointOrigin O, UnitOf<typename O::dimension> U, Representation Rep>
|
||||
class quantity_point;
|
||||
|
||||
template<Kind K, UnitOf<typename K::dimension> U, Representation Rep>
|
||||
@@ -234,10 +234,12 @@ template<Representation ToRep, typename D, typename U, scalable_with_<ToRep> Rep
|
||||
*
|
||||
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
|
||||
*/
|
||||
template<typename CastSpec, typename D, typename U, typename Rep>
|
||||
requires is_specialization_of<CastSpec, quantity_point> ||
|
||||
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); }
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp)
|
||||
template<typename CastSpec, typename O, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& qp)
|
||||
requires requires { requires is_specialization_of<CastSpec, quantity_point>;
|
||||
requires requires { quantity_cast<typename CastSpec::quantity_type>(qp.relative()); };
|
||||
requires equivalent<O, typename CastSpec::origin>; } || // TODO: Simplify when Clang catches up.
|
||||
requires { quantity_cast<CastSpec>(qp.relative()); }
|
||||
{
|
||||
if constexpr (is_specialization_of<CastSpec, quantity_point>)
|
||||
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
|
||||
@@ -261,11 +263,11 @@ template<typename CastSpec, typename D, typename U, typename Rep>
|
||||
* @tparam ToD a dimension type to use for a target quantity
|
||||
* @tparam ToU a unit type to use for a target quantity
|
||||
*/
|
||||
template<Dimension ToD, Unit ToU, typename D, typename U, typename Rep>
|
||||
requires equivalent<ToD, D> && UnitOf<ToU, ToD>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& q)
|
||||
template<Dimension ToD, Unit ToU, typename O, typename U, typename Rep>
|
||||
requires equivalent<ToD, typename O::dimension> && UnitOf<ToU, ToD> && RebindablePointOriginFor<O, ToD>
|
||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<O, U, Rep>& q)
|
||||
{
|
||||
return quantity_point_cast<quantity_point<ToD, ToU, Rep>>(q);
|
||||
return quantity_point_cast<quantity_point<rebind_point_origin_dimension<O, ToD>, ToU, Rep>>(q);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,7 +349,8 @@ template<Kind ToK, Unit ToU, typename K, typename U, typename Rep>
|
||||
template<typename CastSpec, typename PK, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr QuantityPointKind auto quantity_point_kind_cast(const quantity_point_kind<PK, U, Rep>& qpk)
|
||||
requires requires { requires is_specialization_of<CastSpec, quantity_point_kind>;
|
||||
requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); }; } ||
|
||||
requires requires { quantity_kind_cast<typename CastSpec::quantity_kind_type>(qpk.relative()); };
|
||||
requires equivalent<typename PK::origin, typename CastSpec::point_kind_type::origin>; } ||
|
||||
requires { requires PointKind<CastSpec> && UnitOf<U, typename CastSpec::dimension>; } ||
|
||||
requires { quantity_kind_cast<CastSpec>(qpk.relative()); } // TODO: Simplify when Clang catches up.
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace units {
|
||||
/**
|
||||
* @brief A quantity point kind
|
||||
*
|
||||
* An absolute quantity kind with respect to zero (which represents some origin).
|
||||
* An absolute quantity kind measured from an origin.
|
||||
*
|
||||
* @tparam PK the point kind of quantity point
|
||||
* @tparam U the measurement unit of the quantity point kind
|
||||
@@ -45,6 +45,7 @@ class quantity_point_kind {
|
||||
public:
|
||||
using point_kind_type = PK;
|
||||
using kind_type = typename PK::base_kind;
|
||||
using origin = typename point_kind_type::origin;
|
||||
using quantity_kind_type = quantity_kind<kind_type, U, Rep>;
|
||||
using quantity_type = typename quantity_kind_type::quantity_type;
|
||||
using dimension = typename quantity_type::dimension;
|
||||
@@ -64,14 +65,14 @@ public:
|
||||
requires std::constructible_from<quantity_kind_type, T>
|
||||
constexpr explicit quantity_point_kind(T&& t) : qk_(std::forward<T>(t)) {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_point<dimension, U, Rep>& qp) : qk_(qp.relative()) {}
|
||||
constexpr explicit quantity_point_kind(quantity_point<dimension, U, Rep>&& qp) : qk_(std::move(qp).relative()) {}
|
||||
constexpr explicit quantity_point_kind(const quantity_point<origin, U, Rep>& qp) : qk_(qp.relative()) {}
|
||||
constexpr explicit quantity_point_kind(quantity_point<origin, U, Rep>&& qp) : qk_(std::move(qp).relative()) {}
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
requires std::constructible_from<quantity_point<dimension, U, Rep>, QP>
|
||||
requires std::constructible_from<quantity_point<origin, U, Rep>, QP>
|
||||
constexpr explicit quantity_point_kind(const QP& qp) : qk_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||
|
||||
template<QuantityPointKindEquivalentTo<quantity_point_kind> QPK2>
|
||||
template<QuantityPointKindOf<point_kind_type> QPK2>
|
||||
requires std::convertible_to<typename QPK2::quantity_kind_type, quantity_kind_type>
|
||||
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_(qpk.relative()) {}
|
||||
|
||||
@@ -159,20 +160,21 @@ public:
|
||||
return units::quantity_point_kind(lhs.relative() - rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const quantity_point_kind& rhs)
|
||||
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||
[[nodiscard]] friend constexpr QuantityKind auto operator-(const quantity_point_kind& lhs, const QPK& rhs)
|
||||
requires requires(quantity_kind_type qk) { qk - qk; }
|
||||
{
|
||||
return lhs.relative() - rhs.relative();
|
||||
}
|
||||
|
||||
template<QuantityPointKind QPK>
|
||||
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||
requires std::three_way_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point_kind& lhs, const QPK& rhs)
|
||||
{
|
||||
return lhs.relative() <=> rhs.relative();
|
||||
}
|
||||
|
||||
template<QuantityPointKind QPK>
|
||||
template<QuantityPointKindOf<point_kind_type> QPK>
|
||||
requires std::equality_comparable_with<quantity_kind_type, typename QPK::quantity_kind_type>
|
||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point_kind& lhs, const QPK& rhs)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user