forked from mpusz/mp-units
UnitRep concept introduced
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/concepts.h>
|
#include <units/bits/concepts.h>
|
||||||
|
#include <units/bits/customization_points.h>
|
||||||
#include <units/unit.h>
|
#include <units/unit.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@@ -46,11 +47,20 @@ namespace units {
|
|||||||
concept QuantityOf = Quantity<T> && Dimension<D> && same_dim<typename T::dimension, D>;
|
concept QuantityOf = Quantity<T> && Dimension<D> && same_dim<typename T::dimension, D>;
|
||||||
|
|
||||||
// Scalar
|
// Scalar
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Scalar = (!Quantity<T>) && Number<T>;
|
concept Scalar = (!Quantity<T>) && Number<T>;
|
||||||
|
|
||||||
template<Unit U, Scalar Rep>
|
// UnitRep
|
||||||
|
template<typename T>
|
||||||
|
concept UnitRep = Scalar<T> &&
|
||||||
|
(treat_as_floating_point<T> == false ||
|
||||||
|
requires(T&& a) {
|
||||||
|
{ ::units::isfinite(std::forward<T>(a)) } -> bool;
|
||||||
|
{ ::units::isnan(std::forward<T>(a)) } -> bool;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
template<Unit U, UnitRep Rep>
|
||||||
class quantity;
|
class quantity;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -63,7 +73,7 @@ namespace units {
|
|||||||
// common_quantity
|
// common_quantity
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<Quantity Q1, Quantity Q2, Scalar Rep>
|
template<typename Q1, typename Q2, typename Rep>
|
||||||
struct common_quantity_impl;
|
struct common_quantity_impl;
|
||||||
|
|
||||||
template<typename U, typename Rep1, typename Rep2, typename Rep>
|
template<typename U, typename Rep1, typename Rep2, typename Rep>
|
||||||
@@ -81,14 +91,9 @@ namespace units {
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
template<Quantity Q1, Quantity Q2, UnitRep Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
|
||||||
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
||||||
|
|
||||||
// treat_as_floating_point
|
|
||||||
|
|
||||||
template<typename Rep> // TODO Conceptify that
|
|
||||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
|
||||||
|
|
||||||
// quantity_cast
|
// quantity_cast
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -153,7 +158,7 @@ namespace units {
|
|||||||
return cast::cast(q);
|
return cast::cast(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Unit ToU, Scalar ToRep, typename U, typename Rep>
|
template<Unit ToU, UnitRep ToRep, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<ToU, ToRep> quantity_cast(const quantity<U, Rep>& q)
|
[[nodiscard]] constexpr quantity<ToU, ToRep> quantity_cast(const quantity<U, Rep>& q)
|
||||||
{
|
{
|
||||||
return quantity_cast<quantity<ToU, ToRep>>(q);
|
return quantity_cast<quantity<ToU, ToRep>>(q);
|
||||||
@@ -165,7 +170,7 @@ namespace units {
|
|||||||
return quantity_cast<quantity<ToU, Rep>>(q);
|
return quantity_cast<quantity<ToU, Rep>>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar ToRep, typename U, typename Rep>
|
template<UnitRep ToRep, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr quantity<U, ToRep> quantity_cast(const quantity<U, Rep>& q)
|
[[nodiscard]] constexpr quantity<U, ToRep> quantity_cast(const quantity<U, Rep>& q)
|
||||||
{
|
{
|
||||||
return quantity_cast<quantity<U, ToRep>>(q);
|
return quantity_cast<quantity<U, ToRep>>(q);
|
||||||
@@ -173,7 +178,7 @@ namespace units {
|
|||||||
|
|
||||||
// quantity_values
|
// quantity_values
|
||||||
|
|
||||||
template<Scalar Rep>
|
template<UnitRep Rep>
|
||||||
struct quantity_values {
|
struct quantity_values {
|
||||||
static constexpr Rep zero() noexcept { return Rep(0); }
|
static constexpr Rep zero() noexcept { return Rep(0); }
|
||||||
static constexpr Rep one() noexcept { return Rep(1); }
|
static constexpr Rep one() noexcept { return Rep(1); }
|
||||||
@@ -183,7 +188,7 @@ namespace units {
|
|||||||
|
|
||||||
// quantity
|
// quantity
|
||||||
|
|
||||||
template<Unit U, Scalar Rep = double>
|
template<Unit U, UnitRep Rep = double>
|
||||||
class quantity {
|
class quantity {
|
||||||
Rep value_;
|
Rep value_;
|
||||||
|
|
||||||
@@ -196,10 +201,10 @@ namespace units {
|
|||||||
quantity(const quantity&) = default;
|
quantity(const quantity&) = default;
|
||||||
quantity(quantity&&) = default;
|
quantity(quantity&&) = default;
|
||||||
|
|
||||||
template<Scalar Rep2>
|
template<Scalar Value>
|
||||||
requires std::convertible_to<Rep2, rep> &&
|
requires std::convertible_to<Value, rep> &&
|
||||||
(treat_as_floating_point<rep> || (!treat_as_floating_point<Rep2>))
|
(treat_as_floating_point<rep> || (!treat_as_floating_point<Value>))
|
||||||
constexpr explicit quantity(const Rep2& r): value_{static_cast<rep>(r)}
|
constexpr explicit quantity(const Value& r): value_{static_cast<rep>(r)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,9 +269,9 @@ namespace units {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Rep2>
|
template<Scalar Value>
|
||||||
constexpr quantity& operator%=(const Rep2& rhs)
|
constexpr quantity& operator%=(const Value& rhs)
|
||||||
requires (!treat_as_floating_point<rep> && !treat_as_floating_point<Rep2>)
|
requires (!treat_as_floating_point<rep> && !treat_as_floating_point<Value>)
|
||||||
{
|
{
|
||||||
value_ %= rhs;
|
value_ %= rhs;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -304,24 +309,22 @@ namespace units {
|
|||||||
return ret(ret(lhs).count() - ret(rhs).count());
|
return ret(ret(lhs).count() - ret(rhs).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename Rep1, Scalar Rep2>
|
template<typename U, typename Rep1, Scalar Value>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U, Rep1>& q, const Rep2& v)
|
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U, Rep1>& q, const Value& v)
|
||||||
requires (!Quantity<Rep2>)
|
|
||||||
{
|
{
|
||||||
using common_rep = decltype(q.count() * v);
|
using common_rep = decltype(q.count() * v);
|
||||||
using ret = quantity<U, common_rep>;
|
using ret = quantity<U, common_rep>;
|
||||||
return ret(q.count() * v);
|
return ret(q.count() * v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Rep1, typename U, typename Rep2>
|
template<Scalar Value, typename U, typename Rep2>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator*(const Rep1& v, const quantity<U, Rep2>& q)
|
[[nodiscard]] constexpr Quantity AUTO operator*(const Value& v, const quantity<U, Rep2>& q)
|
||||||
requires (!Quantity<Rep1>)
|
|
||||||
{
|
{
|
||||||
return q * v;
|
return q * v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr Scalar AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] constexpr UnitRep AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, dim_invert<typename U2::dimension>>
|
requires same_dim<typename U1::dimension, dim_invert<typename U2::dimension>>
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() * rhs.count());
|
using common_rep = decltype(lhs.count() * rhs.count());
|
||||||
@@ -341,9 +344,8 @@ namespace units {
|
|||||||
return ret(lhs.count() * rhs.count());
|
return ret(lhs.count() * rhs.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Rep1, typename U, typename Rep2>
|
template<Scalar Value, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const Rep1& v, const quantity<U, Rep2>& q)
|
[[nodiscard]] constexpr Quantity AUTO operator/(const Value& v, const quantity<U, Rep>& q)
|
||||||
requires (!Quantity<Rep1>)
|
|
||||||
{
|
{
|
||||||
Expects(q != std::remove_cvref_t<decltype(q)>(0));
|
Expects(q != std::remove_cvref_t<decltype(q)>(0));
|
||||||
|
|
||||||
@@ -353,11 +355,10 @@ namespace units {
|
|||||||
return ret(v / q.count());
|
return ret(v / q.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename Rep1, Scalar Rep2>
|
template<typename U, typename Rep, Scalar Value>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U, Rep1>& q, const Rep2& v)
|
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U, Rep>& q, const Value& v)
|
||||||
requires (!Quantity<Rep2>)
|
|
||||||
{
|
{
|
||||||
Expects(v != Rep2{0});
|
Expects(v != Value{0});
|
||||||
|
|
||||||
using common_rep = decltype(q.count() / v);
|
using common_rep = decltype(q.count() / v);
|
||||||
using ret = quantity<U, common_rep>;
|
using ret = quantity<U, common_rep>;
|
||||||
@@ -365,7 +366,7 @@ namespace units {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||||
[[nodiscard]] constexpr Scalar AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
[[nodiscard]] constexpr UnitRep AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||||
requires same_dim<typename U1::dimension, typename U2::dimension>
|
requires same_dim<typename U1::dimension, typename U2::dimension>
|
||||||
{
|
{
|
||||||
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
||||||
@@ -389,9 +390,9 @@ namespace units {
|
|||||||
return ret(lhs.count() / rhs.count());
|
return ret(lhs.count() / rhs.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename Rep1, Scalar Rep2>
|
template<typename U, typename Rep, Scalar Value>
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U, Rep1>& q, const Rep2& v)
|
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U, Rep>& q, const Value& v)
|
||||||
requires (!treat_as_floating_point<Rep1> && !treat_as_floating_point<Rep2>)
|
requires (!treat_as_floating_point<Rep> && !treat_as_floating_point<Value>)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(q.count() % v);
|
using common_rep = decltype(q.count() % v);
|
||||||
using ret = quantity<U, common_rep>;
|
using ret = quantity<U, common_rep>;
|
||||||
|
Reference in New Issue
Block a user