feat: 💥 delta and absolute construction helpers

This commit is contained in:
Mateusz Pusz committed 2024-06-30 12:03:24 +02:00
1 parent ad3035eafe
commit ba8681f90b
24 files changed
+309 -330

No files matched your search

+1
View File
@@ -50,6 +50,7 @@ add_mp_units_module(
include/mp-units/ext/type_name.h
include/mp-units/ext/type_traits.h
include/mp-units/framework/compare.h
include/mp-units/framework/construction_helpers.h
include/mp-units/framework/customization_points.h
include/mp-units/framework/dimension.h
include/mp-units/framework/dimension_concepts.h
+4 -6
View File
@@ -97,10 +97,8 @@ template<Quantity To, typename From>
if constexpr (q_unit == To::unit) {
// no scaling of the number needed
return {static_cast<MP_UNITS_TYPENAME To::rep>(std::forward<From>(q).numerical_value_is_an_implementation_detail_),
make_delta(To::reference)}; // this is the only (and recommended) way to do
// a truncating conversion on a number, so we are
// using static_cast to suppress all the compiler
// warnings on conversions
To::reference}; // this is the only (and recommended) way to do a truncating conversion on a number, so we
// are using static_cast to suppress all the compiler warnings on conversions
} else {
// scale the number
using traits = magnitude_conversion_traits<To, std::remove_reference_t<From>>;
@@ -108,13 +106,13 @@ template<Quantity To, typename From>
// this results in great assembly
auto res = static_cast<MP_UNITS_TYPENAME To::rep>(
static_cast<traits::c_type>(q.numerical_value_is_an_implementation_detail_) * traits::ratio);
return {res, make_delta(To::reference)};
return {res, To::reference};
} else {
// this is slower but allows conversions like 2000 m -> 2 km without loosing data
auto res = static_cast<MP_UNITS_TYPENAME To::rep>(
static_cast<traits::c_type>(q.numerical_value_is_an_implementation_detail_) * traits::num_mult /
traits::den_mult * traits::irr_mult);
return {res, make_delta(To::reference)};
return {res, To::reference};
}
}
}
+1
View File
@@ -24,6 +24,7 @@
// IWYU pragma: begin_exports
#include <mp-units/framework/compare.h>
#include <mp-units/framework/construction_helpers.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/dimension.h>
#include <mp-units/framework/dimension_concepts.h>
@@ -0,0 +1,67 @@
// 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 <mp-units/framework/quantity.h>
#include <mp-units/framework/quantity_point.h>
#include <mp-units/framework/reference_concepts.h>
#include <mp-units/framework/representation_concepts.h>
#ifndef MP_UNITS_IN_MODULE_INTERFACE
#include <type_traits>
#endif
namespace mp_units {
template<Reference R>
struct delta_ {
template<typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity<R{}, std::remove_cvref_t<Rep>> operator()(Rep&& lhs) const
{
return quantity{std::forward<Rep>(lhs), R{}};
}
};
template<Reference R>
struct absolute_ {
template<typename Rep>
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity_point<R{}, default_point_origin(R{}), std::remove_cvref_t<Rep>> operator()(
Rep&& lhs) const
{
return quantity_point{quantity{std::forward<Rep>(lhs), R{}}};
}
};
MP_UNITS_EXPORT_BEGIN
template<Reference auto R>
inline constexpr delta_<MP_UNITS_REMOVE_CONST(decltype(R))> delta{};
template<Reference auto R>
inline constexpr absolute_<MP_UNITS_REMOVE_CONST(decltype(R))> absolute{};
MP_UNITS_EXPORT_END
} // namespace mp_units
+21 -56
View File
@@ -96,13 +96,8 @@ template<typename Func, Quantity Q1, Quantity Q2>
using common_quantity_for = quantity<common_reference(Q1::reference, Q2::reference),
std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
template<auto T, auto R>
concept SameOriginalReferenceAs =
DeltaReference<MP_UNITS_REMOVE_CONST(decltype(T))> && Reference<MP_UNITS_REMOVE_CONST(decltype(R))> &&
detail::SameReference<remove_reference_specifier(T), R>;
template<auto R1, auto R2, typename Rep1, typename Rep2>
concept SameValueAs = detail::SameOriginalReferenceAs<R1, R2> && std::same_as<Rep1, Rep2>;
concept SameValueAs = detail::SameReference<R1, R2> && std::same_as<Rep1, Rep2>;
} // namespace detail
@@ -133,25 +128,25 @@ public:
[[nodiscard]] static constexpr quantity zero() noexcept
requires requires { quantity_values<rep>::zero(); }
{
return {quantity_values<rep>::zero(), detail::make_delta(R)};
return {quantity_values<rep>::zero(), R};
}
[[nodiscard]] static constexpr quantity one() noexcept
requires requires { quantity_values<rep>::one(); }
{
return {quantity_values<rep>::one(), detail::make_delta(R)};
return {quantity_values<rep>::one(), R};
}
[[nodiscard]] static constexpr quantity min() noexcept
requires requires { quantity_values<rep>::min(); }
{
return {quantity_values<rep>::min(), detail::make_delta(R)};
return {quantity_values<rep>::min(), R};
}
[[nodiscard]] static constexpr quantity max() noexcept
requires requires { quantity_values<rep>::max(); }
{
return {quantity_values<rep>::max(), detail::make_delta(R)};
return {quantity_values<rep>::max(), R};
}
// construction, assignment, destruction
@@ -160,7 +155,7 @@ public:
quantity(quantity&&) = default;
~quantity() = default;
template<typename Value, DeltaReference R2>
template<typename Value, Reference R2>
requires detail::SameValueAs<R2{}, R, std::remove_cvref_t<Value>, Rep>
constexpr quantity(Value&& v, R2) : numerical_value_is_an_implementation_detail_(std::forward<Value>(v))
{
@@ -173,24 +168,6 @@ public:
{
}
template<typename Value, DeltaReference R2>
requires(!Reference<R2>) && (!detail::SameValueAs<R2{}, R, std::remove_cvref_t<Value>, Rep>) &&
detail::QuantityConvertibleTo<
quantity<detail::remove_reference_specifier(R2{}), std::remove_cvref_t<Value>>, quantity>
constexpr quantity(Value&& v, R2) :
quantity(
quantity<detail::remove_reference_specifier(R2{}), std::remove_cvref_t<Value>>{std::forward<Value>(v), R2{}})
{
}
template<typename Value, Reference R2>
requires(!DeltaReference<R2>)
constexpr quantity(Value&&, R2)
{
static_assert(DeltaReference<R2>,
"References using offset units (e.g., temperatures) must be explicitly qualified with `delta`");
}
template<detail::QuantityConvertibleTo<quantity> Q>
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
constexpr explicit(!std::convertible_to<typename Q::rep, Rep>) quantity(const Q& q) :
@@ -206,8 +183,8 @@ public:
convert_explicitly> ||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
!std::convertible_to<typename quantity_like_traits<Q>::rep, Rep>) quantity(const Q& q) :
quantity(::mp_units::quantity{quantity_like_traits<Q>::to_numerical_value(q).value,
detail::make_delta(quantity_like_traits<Q>::reference)})
quantity(
::mp_units::quantity{quantity_like_traits<Q>::to_numerical_value(q).value, quantity_like_traits<Q>::reference})
{
}
@@ -306,7 +283,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{+numerical_value_is_an_implementation_detail_, detail::make_delta(reference)};
return ::mp_units::quantity{+numerical_value_is_an_implementation_detail_, reference};
}
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto operator-() const
@@ -316,7 +293,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{-numerical_value_is_an_implementation_detail_, detail::make_delta(reference)};
return ::mp_units::quantity{-numerical_value_is_an_implementation_detail_, reference};
}
template<typename Q>
@@ -338,7 +315,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_++, detail::make_delta(reference)};
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_++, reference};
}
template<typename Q>
@@ -360,7 +337,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_--, detail::make_delta(reference)};
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_--, reference};
}
// compound assignment operators
@@ -463,16 +440,6 @@ template<typename Value, Reference R>
requires RepresentationOf<Value, get_quantity_spec(R{}).character>
quantity(Value v, R) -> quantity<R{}, Value>;
template<typename Value, DeltaReference R>
requires(!Reference<R>) &&
RepresentationOf<Value, get_quantity_spec(detail::remove_reference_specifier(R{})).character>
quantity(Value v, R) -> quantity<detail::remove_reference_specifier(R{}), Value>;
// the below is needed only to fire static_asserts in the constructor
template<typename Value, Reference R>
requires(!DeltaReference<R>) && RepresentationOf<Value, get_quantity_spec(R{}).character>
quantity(Value v, R) -> quantity<R{}, Value>;
template<QuantityLike Q>
explicit(
is_specialization_of<decltype(quantity_like_traits<Q>::to_numerical_value(std::declval<Q>())), convert_explicitly>)
@@ -487,7 +454,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) + ret_rhs.numerical_value_ref_in(ret::unit),
detail::make_delta(ret::reference)};
ret::reference};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@@ -498,7 +465,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) - ret_rhs.numerical_value_ref_in(ret::unit),
detail::make_delta(ret::reference)};
ret::reference};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@@ -511,15 +478,14 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) % ret_rhs.numerical_value_ref_in(ret::unit),
detail::make_delta(ret::reference)};
ret::reference};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
requires detail::InvocableQuantities<std::multiplies<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
{
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) * rhs.numerical_value_ref_in(get_unit(R2)),
detail::make_delta(R1 * R2)};
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) * rhs.numerical_value_ref_in(get_unit(R2)), R1 * R2};
}
template<auto R, typename Rep, typename Value>
@@ -527,7 +493,7 @@ template<auto R, typename Rep, typename Value>
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const Value&>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const quantity<R, Rep>& q, const Value& v)
{
return quantity{q.numerical_value_ref_in(get_unit(R)) * v, detail::make_delta(R)};
return quantity{q.numerical_value_ref_in(get_unit(R)) * v, R};
}
template<typename Value, auto R, typename Rep>
@@ -535,7 +501,7 @@ template<typename Value, auto R, typename Rep>
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const Value& v, const quantity<R, Rep>& q)
{
return quantity{v * q.numerical_value_ref_in(get_unit(R)), detail::make_delta(R)};
return quantity{v * q.numerical_value_ref_in(get_unit(R)), R};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@@ -543,8 +509,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
{
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) / rhs.numerical_value_ref_in(get_unit(R2)),
detail::make_delta(R1 / R2)};
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) / rhs.numerical_value_ref_in(get_unit(R2)), R1 / R2};
}
template<auto R, typename Rep, typename Value>
@@ -553,7 +518,7 @@ template<auto R, typename Rep, typename Value>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator/(const quantity<R, Rep>& q, const Value& v)
{
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
return quantity{q.numerical_value_ref_in(get_unit(R)) / v, detail::make_delta(R)};
return quantity{q.numerical_value_ref_in(get_unit(R)) / v, R};
}
template<typename Value, auto R, typename Rep>
@@ -562,7 +527,7 @@ template<typename Value, auto R, typename Rep>
[[nodiscard]] constexpr QuantityOf<inverse(get_quantity_spec(R))> auto operator/(const Value& v,
const quantity<R, Rep>& q)
{
return quantity{v / q.numerical_value_ref_in(get_unit(R)), detail::make_delta(::mp_units::one / R)};
return quantity{v / q.numerical_value_ref_in(get_unit(R)), ::mp_units::one / R};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@@ -58,7 +58,7 @@ template<QuantitySpec auto ToQS, typename Q>
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(make_reference(ToQS, std::remove_reference_t<Q>::unit))};
make_reference(ToQS, std::remove_reference_t<Q>::unit)};
}
/**
@@ -129,7 +129,7 @@ struct quantity_spec_interface {
[[nodiscard]] constexpr Quantity auto operator()(this Self self, Q&& q)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(detail::make_reference(self, std::remove_cvref_t<Q>::unit))};
detail::make_reference(self, std::remove_cvref_t<Q>::unit)};
}
#else
template<typename Self_ = Self, UnitOf<Self_{}> U>
@@ -144,7 +144,7 @@ struct quantity_spec_interface {
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit))};
detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit)};
}
#endif
};
@@ -341,7 +341,7 @@ struct quantity_spec<Self, QS, Args...> : detail::propagate_equation<QS>, detail
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit))};
detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit)};
}
#endif
};
+21 -53
View File
@@ -41,16 +41,6 @@ namespace detail {
template<QuantitySpec auto Q, Unit auto U>
using reference_t = reference<MP_UNITS_REMOVE_CONST(decltype(Q)), MP_UNITS_REMOVE_CONST(decltype(U))>;
template<typename R>
requires DeltaReference<R> || AbsoluteReference<R>
[[nodiscard]] consteval Reference auto remove_reference_specifier(R r)
{
if constexpr (requires { R::_original_reference_; })
return R::_original_reference_;
else
return r;
}
} // namespace detail
MP_UNITS_EXPORT_BEGIN
@@ -184,62 +174,40 @@ struct reference {
};
template<typename Rep, DeltaReference R>
requires RepresentationOf<std::remove_cvref_t<Rep>,
get_quantity_spec(detail::remove_reference_specifier(R{})).character>
[[nodiscard]] constexpr quantity<detail::remove_reference_specifier(R{}), std::remove_cvref_t<Rep>> operator*(Rep&& lhs,
R)
template<typename Rep, Reference R>
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>) &&
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity<R{}, std::remove_cvref_t<Rep>> operator*(Rep&& lhs, R)
{
return quantity{std::forward<Rep>(lhs), R{}};
}
template<typename Rep, DeltaReference R>
requires RepresentationOf<std::remove_cvref_t<Rep>,
get_quantity_spec(detail::remove_reference_specifier(R{})).character>
[[nodiscard]] constexpr quantity<inverse(detail::remove_reference_specifier(R{})), std::remove_cvref_t<Rep>> operator/(
Rep&& lhs, R)
template<typename Rep, Reference R>
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>) &&
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[nodiscard]] constexpr quantity<inverse(R{}), std::remove_cvref_t<Rep>> operator/(Rep&& lhs, R)
{
return quantity{std::forward<Rep>(lhs), detail::make_delta(inverse(detail::remove_reference_specifier(R{})))};
}
template<typename Rep, AbsoluteReference R>
requires RepresentationOf<std::remove_cvref_t<Rep>,
get_quantity_spec(detail::remove_reference_specifier(R{})).character>
[[nodiscard]] constexpr quantity_point<detail::remove_reference_specifier(R{}),
default_point_origin(detail::remove_reference_specifier(R{})),
std::remove_cvref_t<Rep>>
operator*(Rep&& lhs, R)
{
return quantity_point{std::forward<Rep>(lhs) * detail::make_delta(detail::remove_reference_specifier(R{}))};
}
template<typename Rep, AbsoluteReference R>
requires RepresentationOf<std::remove_cvref_t<Rep>,
get_quantity_spec(detail::remove_reference_specifier(R{})).character>
[[nodiscard]] constexpr quantity_point<inverse(detail::remove_reference_specifier(R{})),
default_point_origin(detail::remove_reference_specifier(R{})),
std::remove_cvref_t<Rep>>
operator/(Rep&& lhs, R)
{
return quantity_point{std::forward<Rep>(lhs) * detail::make_delta(inverse(detail::remove_reference_specifier(R{})))};
return quantity{std::forward<Rep>(lhs), inverse(R{})};
}
template<typename Rep, Reference R>
requires(!DeltaReference<R>) && RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
requires detail::OffsetUnit<decltype(get_unit(R{}))> &&
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[noreturn]] constexpr auto operator*(Rep&&, R)
{
static_assert(
DeltaReference<R>,
"References using offset units (e.g., temperatures) must be explicitly qualified with `delta` or `absolute`");
static_assert(!detail::OffsetUnit<decltype(get_unit(R{}))>,
"References using offset units (e.g., temperatures) may be constructed only with the `delta` or "
"`absolute` helpers");
}
template<typename Rep, Reference R>
requires(!DeltaReference<R>) && RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
requires detail::OffsetUnit<decltype(get_unit(R{}))> &&
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
[[noreturn]] constexpr auto operator/(Rep&&, R)
{
static_assert(
DeltaReference<R>,
"References using offset units (e.g., temperatures) must be explicitly qualified with `delta` or `absolute`");
static_assert(!detail::OffsetUnit<decltype(get_unit(R{}))>,
"References using offset units (e.g., temperatures) may be constructed only with the `delta` or "
"`absolute` helpers");
}
template<Reference R, typename Rep>
@@ -267,7 +235,7 @@ template<typename Q, Reference R>
[[nodiscard]] constexpr Quantity auto operator*(Q&& q, R)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(std::remove_cvref_t<Q>::reference * R{})};
std::remove_cvref_t<Q>::reference * R{}};
}
template<typename Q, Reference R>
@@ -275,7 +243,7 @@ template<typename Q, Reference R>
[[nodiscard]] constexpr Quantity auto operator/(Q&& q, R)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
detail::make_delta(std::remove_cvref_t<Q>::reference / R{})};
std::remove_cvref_t<Q>::reference / R{}};
}
template<Reference R, typename Q>
@@ -80,44 +80,8 @@ concept ReferenceOf = Reference<T> && QuantitySpecOf<decltype(get_quantity_spec(
MP_UNITS_EXPORT_END
// reference specifiers
template<Reference R>
struct delta_ final {
static constexpr Reference auto _original_reference_ = R{};
};
template<Reference R>
struct absolute_ final {
static constexpr Reference auto _original_reference_ = R{};
};
MP_UNITS_EXPORT_BEGIN
template<Reference auto R>
inline constexpr delta_<MP_UNITS_REMOVE_CONST(decltype(R))> delta{};
template<Reference auto R>
inline constexpr absolute_<MP_UNITS_REMOVE_CONST(decltype(R))> absolute{};
template<typename T>
concept DeltaReference = (Reference<T> && !requires { get_unit(T{}).point_origin; }) || is_specialization_of<T, delta_>;
template<typename T>
concept AbsoluteReference = is_specialization_of<T, absolute_>;
MP_UNITS_EXPORT_END
namespace detail {
template<Reference R>
[[nodiscard]] consteval DeltaReference auto make_delta(R r)
{
if constexpr (requires { get_unit(R{}).point_origin; })
return delta<R{}>;
else
return r;
}
template<auto R1, auto R2>
concept SameReference =
Reference<MP_UNITS_REMOVE_CONST(decltype(R1))> && Reference<MP_UNITS_REMOVE_CONST(decltype(R2))> && (R1 == R2);
@@ -210,4 +210,11 @@ concept UnitCompatibleWith =
Unit<U> && Unit<MP_UNITS_REMOVE_CONST(decltype(FromU))> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
(!AssociatedUnit<U> || UnitOf<U, QS>)&&detail::UnitConvertibleTo<FromU, U{}>;
namespace detail {
template<typename T>
concept OffsetUnit = Unit<T> && requires { T::point_origin; };
}
} // namespace mp_units
+12 -13
View File
@@ -114,8 +114,8 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
[[nodiscard]] constexpr quantity<R, Rep> exp(const quantity<R, Rep>& q)
{
using std::exp;
return value_cast<get_unit(R)>(quantity{static_cast<Rep>(exp(q.force_numerical_value_in(q.unit))),
detail::make_delta(detail::clone_reference_with<one>(R))});
return value_cast<get_unit(R)>(
quantity{static_cast<Rep>(exp(q.force_numerical_value_in(q.unit))), detail::clone_reference_with<one>(R)});
}
/**
@@ -236,7 +236,7 @@ template<auto R, auto S, auto T, typename Rep1, typename Rep2, typename Rep3>
using std::fma;
return quantity{
fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit)),
detail::make_delta(common_reference(R * S, T))};
common_reference(R * S, T)};
}
/**
@@ -260,7 +260,7 @@ template<auto R, auto S, auto T, auto Origin, typename Rep1, typename Rep2, type
using std::fma;
return Origin + quantity{fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit),
b.quantity_ref_from(b.point_origin).numerical_value_ref_in(b.unit)),
detail::make_delta(common_reference(R * S, T))};
common_reference(R * S, T)};
}
/**
@@ -277,7 +277,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::fmod;
return quantity{fmod(x.numerical_value_in(unit), y.numerical_value_in(unit)), detail::make_delta(ref)};
return quantity{fmod(x.numerical_value_in(unit), y.numerical_value_in(unit)), ref};
}
/**
@@ -294,7 +294,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::remainder;
return quantity{remainder(x.numerical_value_in(unit), y.numerical_value_in(unit)), detail::make_delta(ref)};
return quantity{remainder(x.numerical_value_in(unit), y.numerical_value_in(unit)), ref};
}
@@ -338,8 +338,8 @@ template<Unit auto To, auto R, typename Rep>
if constexpr (To == get_unit(R)) {
return {static_cast<Rep>(floor(q.numerical_value_ref_in(q.unit))), detail::clone_reference_with<To>(R)};
} else {
return handle_signed_results(quantity{static_cast<Rep>(floor(q.force_numerical_value_in(To))),
detail::make_delta(detail::clone_reference_with<To>(R))});
return handle_signed_results(
quantity{static_cast<Rep>(floor(q.force_numerical_value_in(To))), detail::clone_reference_with<To>(R)});
}
} else {
if constexpr (To == get_unit(R)) {
@@ -375,8 +375,8 @@ template<Unit auto To, auto R, typename Rep>
if constexpr (To == get_unit(R)) {
return {static_cast<Rep>(ceil(q.numerical_value_ref_in(q.unit))), detail::clone_reference_with<To>(R)};
} else {
return handle_signed_results(quantity{static_cast<Rep>(ceil(q.force_numerical_value_in(To))),
detail::make_delta(detail::clone_reference_with<To>(R))});
return handle_signed_results(
quantity{static_cast<Rep>(ceil(q.force_numerical_value_in(To))), detail::clone_reference_with<To>(R)});
}
} else {
if constexpr (To == get_unit(R)) {
@@ -456,7 +456,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::hypot;
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit)), detail::make_delta(ref)};
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit)), ref};
}
/**
@@ -474,8 +474,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2, auto R3, typename Rep3>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::hypot;
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit), z.numerical_value_in(unit)),
detail::make_delta(ref)};
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit), z.numerical_value_in(unit)), ref};
}
} // namespace mp_units
@@ -27,6 +27,7 @@
#include <mp-units/systems/si/prefixes.h>
#ifndef MP_UNITS_IN_MODULE_INTERFACE
#include <mp-units/framework/construction_helpers.h>
#include <mp-units/framework/quantity_point.h>
#include <mp-units/framework/unit.h>
#endif
@@ -77,7 +78,7 @@ inline constexpr struct weber final : named_unit<"Wb", volt * second> {} weber;
inline constexpr struct tesla final : named_unit<"T", weber / square(metre)> {} tesla;
inline constexpr struct henry final : named_unit<"H", weber / ampere> {} henry;
inline constexpr struct ice_point final : relative_point_origin<273'150 * absolute<milli<kelvin>>> {} ice_point;
inline constexpr struct ice_point final : relative_point_origin<absolute<milli<kelvin>>(273'150)> {} ice_point;
inline constexpr auto zeroth_degree_Celsius = ice_point;
inline constexpr struct degree_Celsius final : named_unit<symbol_text{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius;
+1 -1
View File
@@ -118,7 +118,7 @@ inline constexpr struct troy_pound final : named_unit<"lb t", mag<12> * troy_onc
inline constexpr struct inch_of_mercury final : named_unit<"inHg", mag_ratio<3'386'389, 1'000> * si::pascal> {} inch_of_mercury;
// https://en.wikipedia.org/wiki/United_States_customary_units#Temperature
inline constexpr struct zeroth_degree_Fahrenheit final : relative_point_origin<-32 * absolute<mag_ratio<5, 9> * si::degree_Celsius>> {} zeroth_degree_Fahrenheit;
inline constexpr struct zeroth_degree_Fahrenheit final : relative_point_origin<absolute<mag_ratio<5, 9> * si::degree_Celsius>(-32)> {} zeroth_degree_Fahrenheit;
inline constexpr struct degree_Fahrenheit final : named_unit<symbol_text{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
// clang-format on