mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 02:17:16 +02:00
perf: rvalue references support added for constructors and getters
Resolves #275
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
- perf: value initialization for quantity value removed (left with a default initialization)
|
||||
- perf: limited the `equivalent` trait usage
|
||||
- perf: limited the C++ Standard Library headers usage
|
||||
- perf: rvalue references support added for constructors and getters
|
||||
- (!) fix: `exp()` has sense only for dimensionless quantities
|
||||
- (!) fix: `dim_torque` now properly divides by an angle (instead of multiply) + default unit name change
|
||||
- fix: quantity's operators fixed to behave like the underlying types do
|
||||
|
@ -147,9 +147,10 @@ public:
|
||||
quantity(const quantity&) = default;
|
||||
quantity(quantity&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
constexpr explicit(!(is_same_v<dimension, dim_one> && is_same_v<unit, ::units::one>))
|
||||
quantity(const Value& v) : number_(v) {}
|
||||
template<typename Value>
|
||||
requires safe_convertible_to_<std::remove_cvref_t<Value>, rep>
|
||||
constexpr explicit(!(std::same_as<dimension, dim_one> && std::same_as<unit, ::units::one>))
|
||||
quantity(Value&& v) : number_(std::forward<Value>(v)) {}
|
||||
|
||||
template<safe_castable_to_<quantity> Q>
|
||||
constexpr explicit(false) quantity(const Q& q) : number_(quantity_cast<quantity>(q).number()) {}
|
||||
@ -162,7 +163,10 @@ public:
|
||||
quantity& operator=(quantity&&) = default;
|
||||
|
||||
// data access
|
||||
[[nodiscard]] constexpr rep number() const noexcept { return number_; }
|
||||
[[nodiscard]] constexpr rep& number() & noexcept { return number_; }
|
||||
[[nodiscard]] constexpr const rep& number() const & noexcept { return number_; }
|
||||
[[nodiscard]] constexpr rep&& number() && noexcept { return std::move(number_); }
|
||||
[[nodiscard]] constexpr const rep&& number() const && noexcept { return std::move(number_); }
|
||||
|
||||
// member unary operators
|
||||
[[nodiscard]] constexpr Quantity auto operator+() const
|
||||
|
@ -93,22 +93,28 @@ public:
|
||||
quantity_kind(const quantity_kind&) = default;
|
||||
quantity_kind(quantity_kind&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
||||
constexpr explicit quantity_kind(const Value& v) : q_(v) {}
|
||||
template<typename Value>
|
||||
requires std::same_as<dimension, dim_one> &&
|
||||
safe_convertible_to_<std::remove_cvref_t<Value>, rep> &&
|
||||
std::constructible_from<quantity_type, Value>
|
||||
constexpr explicit quantity_kind(Value&& v) : q_(std::forward<Value>(v)) {}
|
||||
|
||||
template<typename Q>
|
||||
requires (Quantity<Q> || QuantityLike<Q>) && std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_kind(const Q& q) : q_{q} {}
|
||||
requires (Quantity<std::remove_cvref_t<Q>> || QuantityLike<std::remove_cvref_t<Q>>) &&
|
||||
std::constructible_from<quantity_type, Q>
|
||||
constexpr explicit quantity_kind(Q&& q) : q_(std::forward<Q>(q)) {}
|
||||
|
||||
template<QuantityKindEquivalentTo<quantity_kind> QK2>
|
||||
requires std::is_convertible_v<typename QK2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_kind(const QK2& qk) : q_{qk.common()} {}
|
||||
requires std::convertible_to<typename QK2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_kind(const QK2& qk) : q_(qk.common()) {}
|
||||
|
||||
quantity_kind& operator=(const quantity_kind&) = default;
|
||||
quantity_kind& operator=(quantity_kind&&) = default;
|
||||
|
||||
[[nodiscard]] constexpr quantity_type common() const noexcept { return q_; }
|
||||
[[nodiscard]] constexpr quantity_type& common() & noexcept { return q_; }
|
||||
[[nodiscard]] constexpr const quantity_type& common() const & noexcept { return q_; }
|
||||
[[nodiscard]] constexpr quantity_type&& common() && noexcept { return std::move(q_); }
|
||||
[[nodiscard]] constexpr const quantity_type&& common() const && noexcept { return std::move(q_); }
|
||||
|
||||
[[nodiscard]] static constexpr quantity_kind zero() noexcept
|
||||
requires requires { quantity_type::zero(); }
|
||||
|
@ -59,29 +59,33 @@ public:
|
||||
quantity_point(const quantity_point&) = default;
|
||||
quantity_point(quantity_point&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires is_same_v<dimension, dim_one> && std::is_constructible_v<quantity_type, Value>
|
||||
constexpr explicit quantity_point(const Value& v) : q_(v) {}
|
||||
template<typename Value>
|
||||
requires std::same_as<dimension, dim_one> &&
|
||||
safe_convertible_to_<std::remove_cvref_t<Value>, rep> &&
|
||||
std::constructible_from<quantity_type, Value>
|
||||
constexpr explicit quantity_point(Value&& v) : q_(std::forward<Value>(v)) {}
|
||||
|
||||
constexpr explicit quantity_point(const quantity_type& q) : q_{q} {}
|
||||
template<typename Q>
|
||||
requires (Quantity<std::remove_cvref_t<Q>> || QuantityLike<std::remove_cvref_t<Q>>) &&
|
||||
std::constructible_from<quantity_type, Q>
|
||||
constexpr explicit quantity_point(Q&& q) : q_(std::forward<Q>(q)) {}
|
||||
|
||||
template<QuantityLike Q>
|
||||
requires std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_point(const Q& q) : q_{q} {}
|
||||
template<QuantityPoint QP2>
|
||||
requires std::convertible_to<typename QP2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_point(const QP2& qp) : q_(qp.relative()) {}
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
constexpr explicit quantity_point(const QP& qp)
|
||||
requires std::is_constructible_v<quantity_type, decltype(quantity_point_like_traits<QP>::relative(qp))>
|
||||
: q_{quantity_point_like_traits<QP>::relative(qp)} {}
|
||||
|
||||
template<QuantityPoint QP2>
|
||||
requires std::is_convertible_v<typename QP2::quantity_type, quantity_type>
|
||||
constexpr explicit(false) quantity_point(const QP2& qp) : q_{qp.relative()} {}
|
||||
: q_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||
|
||||
quantity_point& operator=(const quantity_point&) = default;
|
||||
quantity_point& operator=(quantity_point&&) = default;
|
||||
|
||||
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; }
|
||||
[[nodiscard]] constexpr quantity_type& relative() & noexcept { return q_; }
|
||||
[[nodiscard]] constexpr const quantity_type& relative() const & noexcept { return q_; }
|
||||
[[nodiscard]] constexpr quantity_type&& relative() && noexcept { return std::move(q_); }
|
||||
[[nodiscard]] constexpr const quantity_type&& relative() const && noexcept { return std::move(q_); }
|
||||
|
||||
[[nodiscard]] static constexpr quantity_point min() noexcept
|
||||
requires requires { quantity_type::min(); }
|
||||
@ -183,14 +187,16 @@ public:
|
||||
{
|
||||
return lhs.relative() == rhs.relative();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<Representation Rep>
|
||||
explicit(false) quantity_point(Rep) -> quantity_point<dim_one, one, Rep>;
|
||||
explicit quantity_point(Rep) -> quantity_point<dim_one, one, Rep>;
|
||||
|
||||
template<Quantity Q>
|
||||
explicit quantity_point(Q) -> quantity_point<typename Q::dimension, typename Q::unit, typename Q::rep>;
|
||||
|
||||
template<QuantityLike Q>
|
||||
quantity_point(Q) -> quantity_point<typename quantity_like_traits<Q>::dimension,
|
||||
explicit quantity_point(Q) -> quantity_point<typename quantity_like_traits<Q>::dimension,
|
||||
typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
|
@ -60,32 +60,28 @@ public:
|
||||
quantity_point_kind(const quantity_point_kind&) = default;
|
||||
quantity_point_kind(quantity_point_kind&&) = default;
|
||||
|
||||
template<safe_convertible_to_<rep> Value>
|
||||
requires std::is_constructible_v<quantity_kind_type, Value>
|
||||
constexpr explicit quantity_point_kind(const Value& v) : qk_(v) {}
|
||||
template<typename T>
|
||||
requires std::constructible_from<quantity_kind_type, T>
|
||||
constexpr explicit quantity_point_kind(T&& t) : qk_(std::forward<T>(t)) {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_type& q) : qk_{q} {}
|
||||
|
||||
template<QuantityLike Q>
|
||||
requires std::is_constructible_v<quantity_type, Q>
|
||||
constexpr explicit quantity_point_kind(const Q& q) : qk_{q} {}
|
||||
constexpr explicit quantity_point_kind(const quantity_point<dimension, U, Rep>& qp) : qk_(qp.relative()) {}
|
||||
constexpr explicit quantity_point_kind(quantity_point<dimension, U, Rep>&& qp) : qk_(std::move(qp).relative()) {}
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
requires std::is_constructible_v<quantity_point<dimension, U, Rep>, QP>
|
||||
constexpr explicit quantity_point_kind(const QP& qp) : qk_{quantity_point_like_traits<QP>::relative(qp)} {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_point<dimension, U, Rep>& qp) : qk_{qp.relative()} {}
|
||||
|
||||
constexpr explicit quantity_point_kind(const quantity_kind_type& qk) : qk_{qk} {}
|
||||
requires std::constructible_from<quantity_point<dimension, U, Rep>, QP>
|
||||
constexpr explicit quantity_point_kind(const QP& qp) : qk_(quantity_point_like_traits<QP>::relative(qp)) {}
|
||||
|
||||
template<QuantityPointKindEquivalentTo<quantity_point_kind> QPK2>
|
||||
requires std::is_convertible_v<typename QPK2::quantity_kind_type, quantity_kind_type>
|
||||
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_{qpk.relative()} {}
|
||||
requires std::convertible_to<typename QPK2::quantity_kind_type, quantity_kind_type>
|
||||
constexpr explicit(false) quantity_point_kind(const QPK2& qpk) : qk_(qpk.relative()) {}
|
||||
|
||||
quantity_point_kind& operator=(const quantity_point_kind&) = default;
|
||||
quantity_point_kind& operator=(quantity_point_kind&&) = default;
|
||||
|
||||
[[nodiscard]] constexpr quantity_kind_type relative() const noexcept { return qk_; }
|
||||
[[nodiscard]] constexpr quantity_kind_type& relative() & noexcept { return qk_; }
|
||||
[[nodiscard]] constexpr const quantity_kind_type& relative() const & noexcept { return qk_; }
|
||||
[[nodiscard]] constexpr quantity_kind_type&& relative() && noexcept { return std::move(qk_); }
|
||||
[[nodiscard]] constexpr const quantity_kind_type&& relative() const && noexcept { return std::move(qk_); }
|
||||
|
||||
[[nodiscard]] static constexpr quantity_point_kind min() noexcept
|
||||
requires requires { quantity_kind_type::min(); }
|
||||
|
@ -475,9 +475,9 @@ static_assert(same(width<metre, double>(2. * m) - width<metre, int>(3 * m), widt
|
||||
static_assert(same(width<metre, double>(2e3 * m) - width<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
|
||||
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) + width<metre, std::uint8_t>(0 * m)).common().number()), int>);
|
||||
decltype((width<metre, std::uint8_t>(0 * m) + width<metre, std::uint8_t>(0 * m)).common().number()), int&&>);
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(0 * m)).common().number()), int>);
|
||||
decltype((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(0 * m)).common().number()), int&&>);
|
||||
static_assert((width<metre, std::uint8_t>(128 * m) + width<metre, std::uint8_t>(128 * m)).common().number() ==
|
||||
std::uint8_t(128) + std::uint8_t(128));
|
||||
static_assert((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(1 * m)).common().number() ==
|
||||
@ -646,7 +646,7 @@ static_assert(same(width<metre, int>(3 * m) % width<metre, int>(2 * m), width<me
|
||||
|
||||
static_assert(is_same_v<
|
||||
decltype((width<metre, std::uint8_t>(0 * m) % width<metre, std::uint8_t>(0 * m)).common().number()),
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))>);
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, reference<dim_length, metre>, width<metre>>);
|
||||
static_assert(!std::is_invocable_v<std::multiplies<>, width<metre>, height<metre>>);
|
||||
|
@ -269,7 +269,7 @@ static_assert([](auto v) { auto vv = ++v; return std::pair(v, vv); }(123_q_m) ==
|
||||
static_assert([](auto v) { auto vv = v--; return std::pair(v, vv); }(123_q_m) == std::pair(122_q_m, 123_q_m));
|
||||
static_assert([](auto v) { auto vv = --v; return std::pair(v, vv); }(123_q_m) == std::pair(122_q_m, 122_q_m));
|
||||
|
||||
static_assert(is_same_v<decltype((+(short{0} * m)).number()), int>);
|
||||
static_assert(is_same_v<decltype((+(short{0} * m)).number()), int&&>);
|
||||
|
||||
|
||||
////////////////////////
|
||||
@ -406,13 +406,13 @@ static_assert(compare<decltype(1 / 1_q_s), frequency<hertz, std::int64_t>>);
|
||||
static_assert(compare<decltype(quantity{1} / 1_q_s), frequency<hertz, std::int64_t>>);
|
||||
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) / 1_q_s), frequency<scaled_unit<ratio(1, 100), hertz>, std::int64_t>>);
|
||||
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m + std::uint8_t(0) * m).number()), int>);
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m - std::uint8_t(0) * m).number()), int>);
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m + std::uint8_t(0) * m).number()), int&&>);
|
||||
static_assert(is_same_v<decltype((std::uint8_t(0) * m - std::uint8_t(0) * m).number()), int&&>);
|
||||
static_assert((std::uint8_t(128) * m + std::uint8_t(128) * m).number() == std::uint8_t(128) + std::uint8_t(128));
|
||||
static_assert((std::uint8_t(0) * m - std::uint8_t(1) * m).number() == std::uint8_t(0) - std::uint8_t(1));
|
||||
|
||||
static_assert(is_same_v<decltype(((std::uint8_t(0) * m) % (std::uint8_t(0) * m)).number()),
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))>);
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
||||
|
||||
// different representation types
|
||||
static_assert(is_same_v<decltype(1_q_m + 1._q_m), length<metre, long double>>);
|
||||
@ -595,14 +595,14 @@ static_assert(quantity(1) - 2.3 == quantity(1 - 2.3));
|
||||
static_assert(1.2 + quantity(3) == quantity(1.2 + 3));
|
||||
static_assert(1.2 - quantity(3) == quantity(1.2 - 3));
|
||||
|
||||
static_assert(is_same_v<decltype((quantity{std::uint8_t(0)} + quantity{std::uint8_t(0)}).number()), int>);
|
||||
static_assert(is_same_v<decltype((quantity{std::uint8_t(0)} - quantity{std::uint8_t(0)}).number()), int>);
|
||||
static_assert(is_same_v<decltype((quantity{std::uint8_t(0)} + quantity{std::uint8_t(0)}).number()), int&&>);
|
||||
static_assert(is_same_v<decltype((quantity{std::uint8_t(0)} - quantity{std::uint8_t(0)}).number()), int&&>);
|
||||
static_assert((quantity{std::uint8_t(128)} + quantity{std::uint8_t(128)}).number() ==
|
||||
std::uint8_t(128) + std::uint8_t(128));
|
||||
static_assert((quantity{std::uint8_t(0)} - quantity{std::uint8_t(1)}).number() == std::uint8_t(0) - std::uint8_t(1));
|
||||
|
||||
static_assert(is_same_v<decltype((quantity{std::uint8_t(0)} % quantity{std::uint8_t(0)}).number()),
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))>);
|
||||
decltype(std::uint8_t(0) % std::uint8_t(0))&&>);
|
||||
|
||||
static_assert(quantity{2} * (1 * m) == 2_q_m);
|
||||
static_assert(quantity{2} / (1 * m) == 2 / 1_q_m);
|
||||
|
Reference in New Issue
Block a user