diff --git a/example/glide_computer.cpp b/example/glide_computer.cpp index 71423c51..6b079cc8 100644 --- a/example/glide_computer.cpp +++ b/example/glide_computer.cpp @@ -67,8 +67,8 @@ auto get_waypoints() using namespace geographic::literals; using namespace mp_units::international::unit_symbols; static const std::array waypoints = { - waypoint{"EPPR", {54.24772_N, 18.6745_E}, msl_altitude{16. * ft}}, // N54°14'51.8" E18°40'28.2" - waypoint{"EPGI", {53.52442_N, 18.84947_E}, msl_altitude{115. * ft}} // N53°31'27.9" E18°50'58.1" + waypoint{"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft}, // N54°14'51.8" E18°40'28.2" + waypoint{"EPGI", {53.52442_N, 18.84947_E}, mean_sea_level + 115. * ft} // N53°31'27.9" E18°50'58.1" }; return waypoints; } diff --git a/example/unmanned_aerial_vehicle.cpp b/example/unmanned_aerial_vehicle.cpp index 0e2091ed..036abdbe 100644 --- a/example/unmanned_aerial_vehicle.cpp +++ b/example/unmanned_aerial_vehicle.cpp @@ -98,7 +98,7 @@ hae_altitude to_hae(msl_altitude msl, position pos) { const auto geoid_undulation = isq::height(GeographicLibWhatsMyOffset(pos.lat.number_in(si::degree), pos.lon.number_in(si::degree)) * si::metre); - return hae_altitude{msl.absolute() - geoid_undulation}; + return height_above_ellipsoid + (msl.absolute() - geoid_undulation); } @@ -130,7 +130,7 @@ struct MP_UNITS_STD_FMT::formatter : formatter(wpt.msl_alt, wpt.pos)); } diff --git a/src/core/include/mp-units/bits/quantity_point_concepts.h b/src/core/include/mp-units/bits/quantity_point_concepts.h index 8c499385..3f89b510 100644 --- a/src/core/include/mp-units/bits/quantity_point_concepts.h +++ b/src/core/include/mp-units/bits/quantity_point_concepts.h @@ -179,10 +179,12 @@ concept QuantityPointLike = requires(T qp) { requires RepresentationOf::rep, get_quantity_spec(quantity_point_like_traits::reference).character>; requires Quantity::quantity_from_origin(qp))>>; - requires std::constructible_from< - quantity_point::reference, quantity_point_like_traits::point_origin, - typename quantity_point_like_traits::rep>, - decltype(quantity_point_like_traits::quantity_from_origin(qp))>; + { + make_quantity_point::point_origin>( + quantity_point_like_traits::quantity_from_origin(qp)) + } + -> std::same_as::reference, quantity_point_like_traits::point_origin, + typename quantity_point_like_traits::rep>>; }; } // namespace mp_units diff --git a/src/core/include/mp-units/quantity_point.h b/src/core/include/mp-units/quantity_point.h index a7143274..d0fc63ff 100644 --- a/src/core/include/mp-units/quantity_point.h +++ b/src/core/include/mp-units/quantity_point.h @@ -29,6 +29,10 @@ namespace mp_units { +template + requires ReferenceOf, PO.quantity_spec> +[[nodiscard]] constexpr quantity_point make_quantity_point(Q&& q); + template struct absolute_point_origin { static constexpr QuantitySpec auto quantity_spec = QS; @@ -37,7 +41,7 @@ struct absolute_point_origin { template struct relative_point_origin { static constexpr QuantityPoint auto quantity_point = QP; - static constexpr QuantitySpec auto quantity_spec = [](){ + static constexpr QuantitySpec auto quantity_spec = []() { // select the strongest of specs if constexpr (detail::QuantityKindSpec>) return QP.point_origin.quantity_spec; @@ -57,11 +61,6 @@ namespace detail { return po; } -template -using quantity_point_like_type = - quantity_point::reference, quantity_point_like_traits::point_origin, - typename quantity_point_like_traits::rep>; - } // namespace detail /** @@ -113,13 +112,6 @@ public: quantity_point(const quantity_point&) = default; quantity_point(quantity_point&&) = default; - template - requires std::constructible_from && - ReferenceOf, PO.quantity_spec> - constexpr explicit quantity_point(Q&& q, decltype(point_origin) = point_origin) : q_(std::forward(q)) - { - } - template QP> requires std::constructible_from // TODO add perfect forwarding @@ -141,10 +133,10 @@ public: template requires std::same_as::point_origin)>, std::remove_const_t> && - std::convertible_to::quantity_type, quantity_type> - constexpr explicit quantity_point(const QP& qp) : - q_(typename detail::quantity_point_like_type::quantity_type{ - quantity_point_like_traits::quantity_from_origin(qp)}) + std::convertible_to< + quantity::reference, typename quantity_point_like_traits::rep>, + quantity_type> + constexpr explicit quantity_point(const QP& qp) : q_(quantity_point_like_traits::quantity_from_origin(qp)) { } @@ -154,15 +146,12 @@ public: template NewPO> [[nodiscard]] constexpr QuantityPointOf auto point_from(NewPO origin) const { - if constexpr (is_same_v>) { + if constexpr (is_same_v>) return *this; - } else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin) { - auto q = absolute(); - return quantity_point(std::move(q)); - } else { - auto q = absolute() - origin.quantity_point.absolute(); - return quantity_point(std::move(q)); - } + else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin) + return make_quantity_point(absolute()); + else + return make_quantity_point(absolute() - origin.quantity_point.absolute()); } // data access @@ -192,7 +181,7 @@ public: requires detail::QuantityConvertibleTo{}, Rep>> [[nodiscard]] constexpr quantity_point<::mp_units::reference{}, PO, Rep> operator[](U) const { - return quantity_point{*this}; + return make_quantity_point(quantity_from_origin()[U{}]); } // member unary operators @@ -235,6 +224,18 @@ public: q_ -= q; return *this; } + +private: + template + requires ReferenceOf, PO2.quantity_spec> + friend constexpr quantity_point make_quantity_point(Q&&); + + template + requires std::constructible_from && + ReferenceOf, PO.quantity_spec> + constexpr explicit quantity_point(Q&& q) : q_(std::forward(q)) + { + } }; // CTAD @@ -250,9 +251,7 @@ template const quantity& q) requires requires { qp.quantity_from_origin() + q; } { - auto temp = qp.quantity_from_origin() + q; - using q_type = decltype(temp); - return quantity_point(std::move(temp)); + return make_quantity_point(qp.quantity_from_origin() + q); } template @@ -269,7 +268,7 @@ template requires ReferenceOf, PO::quantity_spec> [[nodiscard]] constexpr quantity_point operator+(PO, Q&& q) { - return quantity_point(std::forward(q)); + return make_quantity_point(std::forward(q)); } template @@ -286,9 +285,7 @@ template const quantity& q) requires requires { qp.quantity_from_origin() - q; } { - const auto temp = qp.quantity_from_origin() - q; - using q_type = decltype(temp); - return quantity_point(std::move(temp)); + return make_quantity_point(qp.quantity_from_origin() - q); } template @@ -371,4 +368,12 @@ template QP2> return lhs.absolute() == rhs.absolute(); } +// make_quantity_point +template + requires ReferenceOf, PO.quantity_spec> +[[nodiscard]] constexpr quantity_point make_quantity_point(Q&& q) +{ + return quantity_point(std::forward(q)); +} + } // namespace mp_units diff --git a/test/unit_test/static/chrono_test.cpp b/test/unit_test/static/chrono_test.cpp index 1bab812d..75d87128 100644 --- a/test/unit_test/static/chrono_test.cpp +++ b/test/unit_test/static/chrono_test.cpp @@ -40,7 +40,14 @@ template using time_point = quantity_point, Rep>; static_assert(QuantityLike); +static_assert(!Quantity); +static_assert(!QuantityPoint); +static_assert(!QuantityPointLike); + static_assert(QuantityPointLike); +static_assert(!Quantity); +static_assert(!QuantityLike); +static_assert(!QuantityPoint); // construction - same rep type static_assert( @@ -108,10 +115,8 @@ static_assert(quantity{std::chrono::years{1}} == 31556952 * s); static_assert(quantity{1s} + 1 * s == 2 * s); static_assert(quantity{1s} + 1 * min == 61 * s); static_assert(10 * m / quantity{2s} == 5 * (m / s)); -static_assert(quantity_point{sys_seconds{1s}} + 1 * s == - time_point{2 * s}); -static_assert(quantity_point{sys_seconds{1s}} + 1 * min == - time_point{61 * s}); +static_assert(quantity_point{sys_seconds{1s}} + 1 * s == chrono_point_origin + 2 * s); +static_assert(quantity_point{sys_seconds{1s}} + 1 * min == chrono_point_origin + 61 * s); // to_chrono_duration static_assert(to_chrono_duration(1 * s) == 1s); diff --git a/test/unit_test/static/quantity_point_test.cpp b/test/unit_test/static/quantity_point_test.cpp index f1107273..37c0935f 100644 --- a/test/unit_test/static/quantity_point_test.cpp +++ b/test/unit_test/static/quantity_point_test.cpp @@ -45,8 +45,7 @@ inline constexpr struct ground_level : relative_point_origin { } tower_peak; -inline constexpr struct other_ground_level : - relative_point_origin { +inline constexpr struct other_ground_level : relative_point_origin { } other_ground_level; inline constexpr struct other_absolute_level : absolute_point_origin { @@ -281,22 +280,22 @@ static_assert(!std::convertible_to, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); -static_assert(std::constructible_from, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); -static_assert(std::constructible_from, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); -static_assert(std::constructible_from, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); -static_assert(std::constructible_from, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); -static_assert(std::constructible_from, quantity>); +static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity_point>); // different dimensions