UnitRep concept introduced

This commit is contained in:
Mateusz Pusz
2019-11-06 20:17:16 +00:00
parent 1b312b1102
commit e4cd4ea8c8

View File

@@ -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>;