diff --git a/src/include/units/bits/external/hacks.h b/src/include/units/bits/external/hacks.h index b5f0a517..77311c01 100644 --- a/src/include/units/bits/external/hacks.h +++ b/src/include/units/bits/external/hacks.h @@ -60,7 +60,7 @@ namespace std { template concept default_constructible = constructible_from; -#elif COMP_CLANG +#elif !COMP_CLANG // concepts using concepts::three_way_comparable; diff --git a/src/include/units/one_rep.h b/src/include/units/one_rep.h index 4e2573b9..3e5db637 100644 --- a/src/include/units/one_rep.h +++ b/src/include/units/one_rep.h @@ -82,9 +82,10 @@ struct one_rep { template [[nodiscard]] friend constexpr Rep operator/(one_rep, const Rep&) = delete; - template + template [[nodiscard]] constexpr operator Rep() const noexcept { + static_assert(QuantityValue); return quantity_values::one(); } diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 8e604cfa..dd388be9 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -50,7 +50,7 @@ template concept harmonic_ = // exposition only Quantity && Quantity && - requires(QFrom from, QTo to) { requires is_integral(detail::quantity_ratio(from) / detail::quantity_ratio(to)); }; + is_integral(detail::quantity_ratio / detail::quantity_ratio); template concept safe_castable_to_ = // exposition only @@ -136,6 +136,11 @@ public: constexpr explicit(!(is_same_v && is_same_v)) quantity(const Value& v) : value_(v) {} + template Value> + requires is_same_v> + constexpr explicit(!(is_same_v> && unit::ratio == ratio{1, 1, 0})) + quantity(const Value& v) : value_(v) {} + template Q> constexpr explicit(false) quantity(const Q& q) : value_(quantity_cast(q).count()) {} @@ -269,30 +274,30 @@ public: // Below friend functions are to be found via argument-dependent lookup only template [[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const Value& rhs) - requires (!Quantity) && is_same_v && - invoke_result_convertible_to_, rep, Value> + requires requires { requires !Quantity; requires is_same_v; + requires invoke_result_convertible_to_, rep, Value>; } { return units::quantity(lhs.count() + rhs); } template [[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const quantity& rhs) - requires (!Quantity) && is_same_v && - invoke_result_convertible_to_, Value, rep> + requires requires { requires !Quantity; requires is_same_v; + requires invoke_result_convertible_to_, Value, rep>; } { return units::quantity(lhs + rhs.count()); } template [[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const Value& rhs) - requires (!Quantity) && is_same_v && - invoke_result_convertible_to_, rep, Value> + requires requires { requires !Quantity; requires is_same_v; + requires invoke_result_convertible_to_, rep, Value>; } { return units::quantity(lhs.count() - rhs); } template [[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const quantity& rhs) - requires (!Quantity) && is_same_v && - invoke_result_convertible_to_, Value, rep> + requires requires { requires !Quantity; requires is_same_v; + requires invoke_result_convertible_to_, Value, rep>; } { return units::quantity(lhs - rhs.count()); } diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index accb2c0a..06b8a1ca 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -50,8 +50,11 @@ class quantity_point_kind; namespace detail { +template + inline constexpr ratio quantity_ratio = std::enable_if_t>{}; + template -constexpr auto quantity_ratio(const quantity&) +inline constexpr ratio quantity_ratio> = [] { if constexpr(BaseDimension) { return U::ratio; @@ -59,18 +62,18 @@ constexpr auto quantity_ratio(const quantity&) else { return D::base_units_ratio * U::ratio / D::coherent_unit::ratio; } -} +}(); -template -constexpr ratio cast_ratio(const Q1& from, const Q2& to) +template +constexpr ratio cast_ratio(const QFrom& from, const QTo& to) { - using FromU = TYPENAME Q1::unit; - using ToU = TYPENAME Q2::unit; + using FromU = TYPENAME QFrom::unit; + using ToU = TYPENAME QTo::unit; if constexpr(same_unit_reference::value) { return FromU::ratio / ToU::ratio; } else { - return quantity_ratio(from) / quantity_ratio(to); + return quantity_ratio / quantity_ratio; } } diff --git a/test/unit_test/static/quantity_test.cpp b/test/unit_test/static/quantity_test.cpp index 6d945ec8..90fa46cc 100644 --- a/test/unit_test/static/quantity_test.cpp +++ b/test/unit_test/static/quantity_test.cpp @@ -44,6 +44,11 @@ using namespace unit_constants; constexpr auto cgs_cm = cgs::unit_constants::cm; +#if UNITS_DOWNCAST_MODE == 0 +template +constexpr bool is_same_v = equivalent; +#endif + ////////////////////////////// // quantity class invariants @@ -743,7 +748,7 @@ static_assert(quantity_cast(2000.0_q_m / 3600.0_q static_assert(quantity_cast(1 * cgs_cm) == 1 * cm); static_assert(is_same_v(2_q_dm3)), volume>); -static_assert(!is_same_v(2_q_dm3)), volume>); +static_assert(!std::same_as(2_q_dm3)), volume>); //////////////// // downcasting diff --git a/test/unit_test/static/test_tools.h b/test/unit_test/static/test_tools.h index 47a8463e..448504db 100644 --- a/test/unit_test/static/test_tools.h +++ b/test/unit_test/static/test_tools.h @@ -45,8 +45,10 @@ constexpr bool constructible_from(Vs...) { return std::constructible_from; } +template void convertible_from__(T); + template -concept convertible_from_ = requires(Us... us) { [](T) {}({us...}); }; +concept convertible_from_ = requires(Us... us) { convertible_from__({us...}); }; template constexpr bool convertible_from(Vs...) {