Skip to content

Commit

Permalink
feat: equivalent point origins handling improved
Browse files Browse the repository at this point in the history
  • Loading branch information
mpusz committed Dec 3, 2023
1 parent 7b751d8 commit 40c2ecb
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 29 deletions.
52 changes: 23 additions & 29 deletions src/core/include/mp-units/quantity_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ class quantity_point {
// TODO add perfect forwarding
constexpr explicit(!std::convertible_to<typename QP::quantity_type, quantity_type>) quantity_point(const QP& qp) :
quantity_from_origin_is_an_implementation_detail_([&] {
if constexpr (is_same_v<std::remove_const_t<decltype(point_origin)>,
std::remove_const_t<decltype(QP::point_origin)>>)
if constexpr (point_origin == QP::point_origin)
return qp.quantity_ref_from(point_origin);
else
return qp - point_origin;
Expand All @@ -167,11 +166,10 @@ class quantity_point {
}

template<QuantityPointLike QP>
requires std::same_as<std::remove_const_t<decltype(quantity_point_like_traits<QP>::point_origin)>,
std::remove_const_t<decltype(point_origin)>> &&
std::convertible_to<
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
quantity_type>
requires(quantity_point_like_traits<QP>::point_origin == point_origin) &&
std::convertible_to<
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
quantity_type>
constexpr explicit(
is_specialization_of<decltype(quantity_point_like_traits<QP>::to_quantity(std::declval<QP>())),
convert_explicitly> ||
Expand All @@ -196,19 +194,22 @@ class quantity_point {
}

// data access
template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
template<PointOrigin PO2>
requires(PO2{} == point_origin)
[[nodiscard]] constexpr quantity_type& quantity_ref_from(PO2) & noexcept
{
return quantity_from_origin_is_an_implementation_detail_;
}

template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
template<PointOrigin PO2>
requires(PO2{} == point_origin)
[[nodiscard]] constexpr const quantity_type& quantity_ref_from(PO2) const& noexcept
{
return quantity_from_origin_is_an_implementation_detail_;
}

template<std::same_as<std::remove_const_t<decltype(PO)>> PO2>
template<PointOrigin PO2>
requires(PO2{} == point_origin)
constexpr const quantity_type&& quantity_ref_from(PO2) const&& noexcept = delete;

template<PointOrigin PO2>
Expand All @@ -235,10 +236,9 @@ class quantity_point {

// conversion operators
template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>>
requires std::same_as<std::remove_const_t<decltype(point_origin)>,
std::remove_const_t<decltype(quantity_point_like_traits<QP>::point_origin)>> &&
std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
typename quantity_point_like_traits<QP>::rep>>
requires(point_origin == quantity_point_like_traits<QP>::point_origin) &&
std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
typename quantity_point_like_traits<QP>::rep>>
[[nodiscard]] explicit(
is_specialization_of<
decltype(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)),
Expand All @@ -253,10 +253,9 @@ class quantity_point {
}

template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>>
requires std::same_as<std::remove_const_t<decltype(point_origin)>,
std::remove_const_t<decltype(quantity_point_like_traits<QP>::point_origin)>> &&
std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
typename quantity_point_like_traits<QP>::rep>>
requires(point_origin == quantity_point_like_traits<QP>::point_origin) &&
std::convertible_to<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
typename quantity_point_like_traits<QP>::rep>>
[[nodiscard]] explicit(
is_specialization_of<
decltype(quantity_point_like_traits<QP>::from_quantity(quantity_from_origin_is_an_implementation_detail_)),
Expand Down Expand Up @@ -390,8 +389,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
// TODO consider constraining it for both branches
requires requires { lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
{
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
std::remove_const_t<decltype(QP2::point_origin)>>)
if constexpr (QP1::point_origin == QP2::point_origin)
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin);
else
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin) +
Expand All @@ -402,17 +400,15 @@ template<PointOrigin PO, QuantityPointOf<PO{}> QP>
requires ReferenceOf<std::remove_const_t<decltype(QP::reference)>, PO::quantity_spec>
[[nodiscard]] constexpr Quantity auto operator-(const QP& qp, PO po)
{
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>, std::remove_const_t<PO>>)
if constexpr (QP::point_origin == po)
return qp.quantity_ref_from(QP::point_origin);
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) {
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
std::remove_const_t<decltype(QP::absolute_point_origin)>>)
if constexpr (QP::point_origin == QP::absolute_point_origin)
return qp.quantity_ref_from(QP::point_origin);
else
return qp.quantity_ref_from(QP::point_origin) + (qp.point_origin - qp.absolute_point_origin);
} else {
if constexpr (is_same_v<std::remove_const_t<decltype(QP::point_origin)>,
std::remove_const_t<decltype(po.quantity_point.point_origin)>>)
if constexpr (QP::point_origin == po.quantity_point.point_origin)
return qp.quantity_ref_from(QP::point_origin) -
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin);
else
Expand Down Expand Up @@ -448,8 +444,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
requires std::three_way_comparable_with<typename QP1::quantity_type, typename QP2::quantity_type>
[[nodiscard]] constexpr auto operator<=>(const QP1& lhs, const QP2& rhs)
{
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
std::remove_const_t<decltype(QP2::point_origin)>>)
if constexpr (QP1::point_origin == QP2::point_origin)
return lhs.quantity_ref_from(QP1::point_origin) <=> rhs.quantity_ref_from(QP2::point_origin);
else
return lhs - lhs.absolute_point_origin <=> rhs - rhs.absolute_point_origin;
Expand All @@ -459,8 +454,7 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
requires std::equality_comparable_with<typename QP1::quantity_type, typename QP2::quantity_type>
[[nodiscard]] constexpr bool operator==(const QP1& lhs, const QP2& rhs)
{
if constexpr (is_same_v<std::remove_const_t<decltype(QP1::point_origin)>,
std::remove_const_t<decltype(QP2::point_origin)>>)
if constexpr (QP1::point_origin == QP2::point_origin)
return lhs.quantity_ref_from(QP1::point_origin) == rhs.quantity_ref_from(QP2::point_origin);
else
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
Expand Down
34 changes: 34 additions & 0 deletions test/unit_test/static/quantity_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,40 @@ static_assert(quantity_point{sys_seconds{24h}}.unit == si::second);
static_assert(quantity_point{sys_seconds{24h}}.quantity_spec == kind_of<isq::time>);


// ////////////
// // getters
// ////////////

constexpr quantity_point mean_sea_level_qp = mean_sea_level + 1 * m;
constexpr quantity_point my_mean_sea_level_qp = my_mean_sea_level + 1 * m;
constexpr quantity_point ground_level_qp = ground_level + 1 * m;
constexpr quantity_point my_ground_level_qp = my_ground_level + 1 * m;
constexpr quantity_point same_ground_level1_qp = same_ground_level1 + 1 * m;
constexpr quantity_point same_ground_level2_qp = same_ground_level2 + 1 * m;

static_assert(mean_sea_level_qp.quantity_ref_from(mean_sea_level) == 1 * m);
static_assert(mean_sea_level_qp.quantity_ref_from(my_mean_sea_level) == 1 * m);
static_assert(my_mean_sea_level_qp.quantity_ref_from(my_mean_sea_level) == 1 * m);
static_assert(my_mean_sea_level_qp.quantity_ref_from(mean_sea_level) == 1 * m);

static_assert(ground_level_qp.quantity_ref_from(ground_level) == 1 * m);
static_assert(ground_level_qp.quantity_ref_from(my_ground_level) == 1 * m);
static_assert(ground_level_qp.quantity_ref_from(same_ground_level1) == 1 * m);
static_assert(ground_level_qp.quantity_ref_from(same_ground_level2) == 1 * m);
static_assert(my_ground_level_qp.quantity_ref_from(my_ground_level) == 1 * m);
static_assert(my_ground_level_qp.quantity_ref_from(ground_level) == 1 * m);
static_assert(my_ground_level_qp.quantity_ref_from(same_ground_level1) == 1 * m);
static_assert(my_ground_level_qp.quantity_ref_from(same_ground_level2) == 1 * m);
static_assert(same_ground_level1_qp.quantity_ref_from(my_ground_level) == 1 * m);
static_assert(same_ground_level1_qp.quantity_ref_from(ground_level) == 1 * m);
static_assert(same_ground_level1_qp.quantity_ref_from(same_ground_level1) == 1 * m);
static_assert(same_ground_level1_qp.quantity_ref_from(same_ground_level2) == 1 * m);
static_assert(same_ground_level2_qp.quantity_ref_from(my_ground_level) == 1 * m);
static_assert(same_ground_level2_qp.quantity_ref_from(ground_level) == 1 * m);
static_assert(same_ground_level2_qp.quantity_ref_from(same_ground_level1) == 1 * m);
static_assert(same_ground_level2_qp.quantity_ref_from(same_ground_level2) == 1 * m);


////////////////////////
// assignment operator
////////////////////////
Expand Down

0 comments on commit 40c2ecb

Please sign in to comment.