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.
|
||||
|
||||
Reference in New Issue
Block a user