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
+54 -3
View File
@@ -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>;
};
+25 -6
View File
@@ -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>
+6 -7
View File
@@ -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.