fix: improve downcast mode off

This commit is contained in:
Johel Ernesto Guerrero Peña
2022-03-28 10:17:46 -04:00
parent 6c2c8748e7
commit 146f1d1c83
9 changed files with 196 additions and 192 deletions

View File

@ -45,6 +45,12 @@ inline constexpr auto make_quantity = [](auto&& v) {
return quantity<typename decltype(R)::dimension, typename decltype(R)::unit, Rep>(std::forward<decltype(v)>(v));
};
template<typename T>
concept quantity_one =
Quantity<T> &&
(std::same_as<typename T::dimension, dim_one> || std::same_as<typename T::dimension, unknown_dimension<>>) &&
detail::equivalent_unit<typename T::unit, typename T::dimension, ::units::one, typename T::dimension>::value;
} // namespace detail
template<typename T>
@ -133,8 +139,7 @@ public:
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))
constexpr explicit(!detail::quantity_one<quantity>) quantity(Value&& v) : number_(std::forward<Value>(v))
{
}
@ -252,9 +257,9 @@ public:
number_ *= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity& operator*=(const dimensionless<units::one, Rep2>& rhs)
requires requires(rep a, const Rep2 b) {
template<detail::quantity_one Q>
constexpr quantity& operator*=(const Q& rhs)
requires requires(rep a, const typename Q::rep b) {
{
a *= b
} -> std::same_as<rep&>;
@ -276,15 +281,15 @@ public:
number_ /= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity& operator/=(const dimensionless<units::one, Rep2>& rhs)
requires requires(rep a, const Rep2 b) {
template<detail::quantity_one Q>
constexpr quantity& operator/=(const Q& rhs)
requires requires(rep a, const typename Q::rep b) {
{
a /= b
} -> std::same_as<rep&>;
}
{
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
number_ /= rhs.number();
return *this;
}
@ -302,15 +307,15 @@ public:
return *this;
}
template<typename Rep2>
constexpr quantity& operator%=(const dimensionless<units::one, Rep2>& rhs)
requires(!floating_point_<rep>) && (!floating_point_<Rep2>) && requires(rep a, const Rep2 b) {
{
a %= b
} -> std::same_as<rep&>;
}
template<detail::quantity_one Q>
constexpr quantity& operator%=(const Q& rhs)
requires(!floating_point_<rep>) && (!floating_point_<typename Q::rep>) && requires(rep a, const typename Q::rep b) {
{
a %= b
} -> std::same_as<rep&>;
}
{
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
number_ %= rhs.number();
return *this;
}

View File

@ -54,6 +54,10 @@ inline constexpr auto downcasted_kind_fn = [](auto q) {
template<QuantityKind QK>
inline constexpr auto& downcasted_kind = downcasted_kind_fn<typename QK::kind_type::base_kind>;
template<typename T, typename K>
concept quantity_kind_one = QuantityKind<T> && equivalent<typename T::kind_type, downcast_kind<K, dim_one>> &&
detail::quantity_one<typename T::quantity_type>;
} // namespace detail
/**
@ -198,8 +202,8 @@ public:
q_ *= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity_kind& operator*=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator*=(const QK& rhs)
requires requires(quantity_type q) { q *= rhs.common(); }
{
q_ *= rhs.common();
@ -214,8 +218,8 @@ public:
q_ /= rhs;
return *this;
}
template<typename Rep2>
constexpr quantity_kind& operator/=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
template<detail::quantity_kind_one<K> QK>
constexpr quantity_kind& operator/=(const QK& rhs)
requires requires(quantity_type q) { q /= rhs.common(); }
{
q_ /= rhs.common();
@ -233,8 +237,7 @@ public:
template<QuantityKind QK>
constexpr quantity_kind& operator%=(const QK& rhs)
requires(QuantityKindEquivalentTo<QK, quantity_kind> ||
std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
requires(QuantityKindEquivalentTo<QK, quantity_kind> || detail::quantity_kind_one<QK, K>) &&
requires(quantity_type q) { q %= rhs.common(); }
{
gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero());

View File

@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "test_tools.h"
#include <units/bits/external/type_traits.h>
#include <units/chrono.h>
#include <units/isq/si/length.h>
@ -82,12 +83,12 @@ static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_c
// CTAD
static_assert(is_same_v<decltype(quantity{1s}), si::time<si::second, std::chrono::seconds::rep>>);
static_assert(is_same_v<decltype(quantity{1h}), si::time<si::hour, std::chrono::hours::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_seconds{1s}}),
time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_days{sys_days::duration{1}}}),
time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
static_assert(compare<decltype(quantity{1s}), si::time<si::second, std::chrono::seconds::rep>>);
static_assert(compare<decltype(quantity{1h}), si::time<si::hour, std::chrono::hours::rep>>);
static_assert(compare<decltype(quantity_point{sys_seconds{1s}}),
time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
static_assert(compare<decltype(quantity_point{sys_days{sys_days::duration{1}}}),
time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
// operators
static_assert(quantity{1s} + 1_q_s == 2_q_s);

View File

@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "test_tools.h"
#include <units/bits/equivalent.h>
#include <units/bits/external/downcasting.h>
#include <units/bits/external/type_traits.h>
@ -62,7 +63,7 @@ static_assert(!PointKind<azimuth::_kind_base>);
static_assert(is_same_v<radius::base_kind, radius>);
static_assert(is_same_v<radius::dimension, dim_length>);
static_assert(is_same_v<downcast_result<radius>, downcast_kind<radius, dim_length>>);
static_assert(compare<downcast_result<radius>, downcast_kind<radius, dim_length>>);
static_assert(equivalent<radius, radius>);
static_assert(equivalent<radius, radius::kind>);
@ -124,7 +125,7 @@ static_assert(PointKind<abscissa::_point_kind_base>);
static_assert(is_same_v<abscissa::base_kind, width>);
static_assert(is_same_v<abscissa::dimension, dim_length>);
static_assert(is_same_v<downcast_result<abscissa>, downcast_point_kind<width>>);
static_assert(compare<downcast_result<abscissa>, downcast_point_kind<width>>);
static_assert(equivalent<abscissa, abscissa>);
static_assert(equivalent<abscissa, abscissa::point_kind>);
@ -162,8 +163,8 @@ static_assert(!PointKind<rate_of_climb::_kind_base>);
static_assert(is_same_v<rate_of_climb::base_kind, height>);
static_assert(is_same_v<rate_of_climb::dimension, dim_speed>);
static_assert(is_same_v<downcast_result<rate_of_climb>, downcast_kind<rate_of_climb, dim_speed>>);
static_assert(is_same_v<downcast_result<rate_of_climb>, downcast_kind<height, dim_speed>>);
static_assert(compare<downcast_result<rate_of_climb>, downcast_kind<rate_of_climb, dim_speed>>);
static_assert(compare<downcast_result<rate_of_climb>, downcast_kind<height, dim_speed>>);
static_assert(equivalent<rate_of_climb, rate_of_climb>);
static_assert(equivalent<rate_of_climb, rate_of_climb::derived_kind>);
@ -181,7 +182,7 @@ static_assert(PointKind<velocity_of_climb::_point_kind_base>);
static_assert(is_same_v<velocity_of_climb::base_kind, rate_of_climb>);
static_assert(is_same_v<velocity_of_climb::dimension, dim_speed>);
static_assert(is_same_v<downcast_result<velocity_of_climb>, downcast_point_kind<rate_of_climb>>);
static_assert(compare<downcast_result<velocity_of_climb>, downcast_point_kind<rate_of_climb>>);
static_assert(equivalent<velocity_of_climb, velocity_of_climb>);
static_assert(equivalent<velocity_of_climb, velocity_of_climb::point_kind>);
@ -200,6 +201,6 @@ static_assert(!equivalent<height::_kind_base, velocity_of_climb::_point_kind_bas
static_assert(!equivalent<rate_of_climb, velocity_of_climb>);
static_assert(!equivalent<rate_of_climb::_kind_base, velocity_of_climb::_point_kind_base>);
static_assert(is_same_v<downcast_result<height>, downcast_kind<rate_of_climb, dim_length>>);
static_assert(compare<downcast_result<height>, downcast_kind<rate_of_climb, dim_length>>);
} // namespace

View File

@ -481,11 +481,11 @@ static_assert(invalid_compound_assignments_<time_kind, second, std::chrono::seco
static_assert(same(width<metre, int>(2 * m) + width<metre, int>(3 * m), width<metre, int>(5 * m)));
static_assert(same(width<metre, int>(2 * m) + width<metre, double>(3. * m), width<metre, double>(5. * m)));
static_assert(same(width<metre, double>(2. * m) + width<metre, int>(3 * m), width<metre, double>(5. * m)));
static_assert(same(width<kilometre, int>(2 * km) + width<metre, double>(3e3 * m), width<metre, double>(5e3 * m)));
static_assert(comp(width<kilometre, int>(2 * km) + width<metre, double>(3e3 * m), width<metre, double>(5e3 * m)));
static_assert(same(width<metre, int>(2 * m) - width<metre, int>(3 * m), width<metre, int>(-1 * m)));
static_assert(same(width<metre, int>(2 * m) - width<metre, double>(3. * m), width<metre, double>(-1. * m)));
static_assert(same(width<metre, double>(2. * m) - width<metre, int>(3 * m), width<metre, double>(-1. * m)));
static_assert(same(width<metre, double>(2e3 * m) - width<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
static_assert(comp(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()),
@ -531,131 +531,131 @@ static_assert(same(2 * width<metre, int>(3 * m), width<metre, int>(6 * m)));
static_assert(same(2 * width<metre, double>(3. * m), width<metre, double>(6. * m)));
static_assert(same(2. * width<metre, int>(3 * m), width<metre, double>(6. * m)));
static_assert(same(width<metre, int>(2 * m) * quantity(3), width<metre, int>(6 * m)));
static_assert(same(width<metre, int>(2 * m) * quantity(3.), width<metre, double>(6. * m)));
static_assert(same(width<metre, double>(2. * m) * quantity(3), width<metre, double>(6. * m)));
static_assert(same(quantity(2) * width<metre, int>(3 * m), width<metre, int>(6 * m)));
static_assert(same(quantity(2) * width<metre, double>(3. * m), width<metre, double>(6. * m)));
static_assert(same(quantity(2.) * width<metre, int>(3 * m), width<metre, double>(6. * m)));
static_assert(comp(width<metre, int>(2 * m) * quantity(3), width<metre, int>(6 * m)));
static_assert(comp(width<metre, int>(2 * m) * quantity(3.), width<metre, double>(6. * m)));
static_assert(comp(width<metre, double>(2. * m) * quantity(3), width<metre, double>(6. * m)));
static_assert(comp(quantity(2) * width<metre, int>(3 * m), width<metre, int>(6 * m)));
static_assert(comp(quantity(2) * width<metre, double>(3. * m), width<metre, double>(6. * m)));
static_assert(comp(quantity(2.) * width<metre, int>(3 * m), width<metre, double>(6. * m)));
static_assert(same(width<metre, int>(2 * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
static_assert(comp(width<metre, int>(2 * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
width<metre, int>(6 * m)));
static_assert(same(width<metre, int>(2 * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3.),
static_assert(comp(width<metre, int>(2 * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3.),
width<metre, double>(6. * m)));
static_assert(same(width<metre, double>(2. * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
static_assert(comp(width<metre, double>(2. * m) * quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
width<metre, double>(6. * m)));
static_assert(same(quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(2) * width<metre, int>(3 * m),
static_assert(comp(quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(2) * width<metre, int>(3 * m),
width<metre, int>(6 * m)));
static_assert(same(quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(2) * width<metre, double>(3. * m),
static_assert(comp(quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(2) * width<metre, double>(3. * m),
width<metre, double>(6. * m)));
static_assert(same(quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(2.) * width<metre, int>(3 * m),
static_assert(comp(quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(2.) * width<metre, int>(3 * m),
width<metre, double>(6. * m)));
static_assert(same(height<metre, int>(2 * m) * (3 * Hz), rate_of_climb<metre_per_second, int>(6 * (m / s))));
static_assert(same(height<metre, int>(2 * m) * (3. * Hz), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(same(height<metre, double>(2. * m) * (3 * Hz), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(same((2 * Hz) * height<metre, int>(3 * m), rate_of_climb<metre_per_second, int>(6 * (m / s))));
static_assert(same((2 * Hz) * height<metre, double>(3. * m), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(same((2. * Hz) * height<metre, int>(3 * m), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(comp(height<metre, int>(2 * m) * (3 * Hz), rate_of_climb<metre_per_second, int>(6 * (m / s))));
static_assert(comp(height<metre, int>(2 * m) * (3. * Hz), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(comp(height<metre, double>(2. * m) * (3 * Hz), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(comp((2 * Hz) * height<metre, int>(3 * m), rate_of_climb<metre_per_second, int>(6 * (m / s))));
static_assert(comp((2 * Hz) * height<metre, double>(3. * m), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(comp((2. * Hz) * height<metre, int>(3 * m), rate_of_climb<metre_per_second, double>(6. * (m / s))));
static_assert(same(quantity_kind<time_kind, second, int>(2 * s) * (3 * Hz),
static_assert(comp(quantity_kind<time_kind, second, int>(2 * s) * (3 * Hz),
quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(6)));
static_assert(same((3 * Hz) * quantity_kind<time_kind, second, int>(2 * s),
static_assert(comp((3 * Hz) * quantity_kind<time_kind, second, int>(2 * s),
quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(6)));
static_assert(same(apples<one, int>(2) * quantity(2), apples<one, int>(4)));
static_assert(same(quantity(2) * apples<one, int>(2), apples<one, int>(4)));
static_assert(comp(apples<one, int>(2) * quantity(2), apples<one, int>(4)));
static_assert(comp(quantity(2) * apples<one, int>(2), apples<one, int>(4)));
// clang-format off
static_assert(same(width<metre, int>(4 * m) * (1 * m), horizontal_area<square_metre, int>(4 * (m * m))));
static_assert(same(width<metre, int>(2 * m) * width<metre, int>(2 * m), horizontal_area<square_metre, int>(4 * (m * m))));
static_assert(same(width<metre, int>(2 * m) * width<metre, double>(2 * m), horizontal_area<square_metre, double>(4 * (m * m))));
static_assert(same(width<metre, double>(2 * m) * width<metre, int>(2 * m), horizontal_area<square_metre, double>(4 * (m * m))));
static_assert(comp(width<metre, int>(4 * m) * (1 * m), horizontal_area<square_metre, int>(4 * (m * m))));
static_assert(comp(width<metre, int>(2 * m) * width<metre, int>(2 * m), horizontal_area<square_metre, int>(4 * (m * m))));
static_assert(comp(width<metre, int>(2 * m) * width<metre, double>(2 * m), horizontal_area<square_metre, double>(4 * (m * m))));
static_assert(comp(width<metre, double>(2 * m) * width<metre, int>(2 * m), horizontal_area<square_metre, double>(4 * (m * m))));
// clang-format on
static_assert(same(apples<one, int>(2) * apples<one, int>(2), apples<one, int>(4)));
static_assert(same(apples<one, int>(2) * (2 / apples<one, int>(1)), apples<one, int>(4)));
static_assert(comp(apples<one, int>(2) * apples<one, int>(2), apples<one, int>(4)));
static_assert(comp(apples<one, int>(2) * (2 / apples<one, int>(1)), apples<one, int>(4)));
static_assert(same(width<kilometre>(4 * m) * (1 * mm), horizontal_area<square_metre>(4 * (m * mm))));
static_assert(same(width<kilometre>(2 * m) * width<millimetre>(2 * m), horizontal_area<square_metre>(4 * (m * m))));
static_assert(same(width<metre>(2 * m) * (1 / width<metre>(2 * m)),
static_assert(comp(width<kilometre>(4 * m) * (1 * mm), horizontal_area<square_metre>(4 * (m * mm))));
static_assert(comp(width<kilometre>(2 * m) * width<millimetre>(2 * m), horizontal_area<square_metre>(4 * (m * m))));
static_assert(comp(width<metre>(2 * m) * (1 / width<metre>(2 * m)),
quantity_kind<downcast_kind<width_kind, dim_one>, one>(1)));
static_assert(same(width<metre, int>(2 * m) / 3, width<metre, int>(0 * m)));
static_assert(same(width<metre, int>(2 * m) / 3., width<metre, double>(2 / 3. * m)));
static_assert(same(width<metre, double>(2. * m) / 3, width<metre, double>(2. / 3 * m)));
static_assert(same(width<metre, int>(2 * m) / quantity(3), width<metre, int>(0 * m)));
static_assert(same(width<metre, int>(2 * m) / quantity(3.), width<metre, double>(2 / 3. * m)));
static_assert(same(width<metre, double>(2. * m) / quantity(3), width<metre, double>(2. / 3 * m)));
static_assert(comp(width<metre, int>(2 * m) / quantity(3), width<metre, int>(0 * m)));
static_assert(comp(width<metre, int>(2 * m) / quantity(3.), width<metre, double>(2 / 3. * m)));
static_assert(comp(width<metre, double>(2. * m) / quantity(3), width<metre, double>(2. / 3 * m)));
static_assert(same(width<metre, int>(2 * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
static_assert(comp(width<metre, int>(2 * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(3),
width<metre, int>(0 * m)));
static_assert(same(width<metre, int>(2 * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3.),
static_assert(comp(width<metre, int>(2 * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3.),
width<metre, double>(2 / 3. * m)));
static_assert(same(width<metre, double>(2. * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3),
static_assert(comp(width<metre, double>(2. * m) / quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(3),
width<metre, double>(2. / 3 * m)));
static_assert(same(2 / quantity_kind<time_kind, second, int>(3 * s),
static_assert(comp(2 / quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, int>(2 / 3 / (1 * s))));
static_assert(same(2 / quantity_kind<time_kind, second, double>(3. * s),
static_assert(comp(2 / quantity_kind<time_kind, second, double>(3. * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(2. / quantity_kind<time_kind, second, int>(3 * s),
static_assert(comp(2. / quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(quantity(2) / quantity_kind<time_kind, second, int>(3 * s),
static_assert(comp(quantity(2) / quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, int>(2 / 3 / (1 * s))));
static_assert(same(quantity(2) / quantity_kind<time_kind, second, double>(3. * s),
static_assert(comp(quantity(2) / quantity_kind<time_kind, second, double>(3. * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(quantity(2.) / quantity_kind<time_kind, second, int>(3 * s),
static_assert(comp(quantity(2.) / quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
static_assert(comp(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, int>(2 / 3 / (1 * s))));
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
static_assert(comp(quantity_kind<downcast_kind<time_kind, dim_one>, one, int>(2) /
quantity_kind<time_kind, second, double>(3. * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(quantity_kind<downcast_kind<time_kind, dim_one>, one, double>(2.) /
static_assert(comp(quantity_kind<downcast_kind<time_kind, dim_one>, one, double>(2.) /
quantity_kind<time_kind, second, int>(3 * s),
quantity_kind<downcast_kind<time_kind, dim_frequency>, hertz, double>(2 / 3. / (1 * s))));
static_assert(same(height<metre, int>(2 * m) / (3 * s), rate_of_climb<metre_per_second, int>(0 * (m / s))));
static_assert(same(height<metre, int>(2 * m) / (3. * s), rate_of_climb<metre_per_second, double>(2 / 3. * (m / s))));
static_assert(same(height<metre, double>(2. * m) / (3 * s), rate_of_climb<metre_per_second, double>(2. / 3 * (m / s))));
static_assert(comp(height<metre, int>(2 * m) / (3 * s), rate_of_climb<metre_per_second, int>(0 * (m / s))));
static_assert(comp(height<metre, int>(2 * m) / (3. * s), rate_of_climb<metre_per_second, double>(2 / 3. * (m / s))));
static_assert(comp(height<metre, double>(2. * m) / (3 * s), rate_of_climb<metre_per_second, double>(2. / 3 * (m / s))));
static_assert(same(width<metre, int>(2 * m) * dimensionless<percent, int>(3), width<centimetre, int>(6 * cm)));
static_assert(same(dimensionless<percent, int>(2) * width<metre, int>(3 * m), width<centimetre, int>(6 * cm)));
static_assert(same(width<metre, int>(2 * m) / dimensionless<percent, double>(3),
static_assert(comp(width<metre, int>(2 * m) * dimensionless<percent, int>(3), width<centimetre, int>(6 * cm)));
static_assert(comp(dimensionless<percent, int>(2) * width<metre, int>(3 * m), width<centimetre, int>(6 * cm)));
static_assert(comp(width<metre, int>(2 * m) / dimensionless<percent, double>(3),
width<hectometre, double>(2. / 3 * hm)));
static_assert(same(width<metre, int>(2 * m) % dimensionless<percent, int>(3), width<metre, int>(2 * m)));
static_assert(same(height<metre, int>(2 * m) / (3 * m),
static_assert(comp(height<metre, int>(2 * m) / (3 * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, int>(0)));
static_assert(same(height<metre, int>(2 * m) / (3. * m),
static_assert(comp(height<metre, int>(2 * m) / (3. * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, double>(2 / 3.)));
static_assert(same(height<metre, double>(2. * m) / (3 * m),
static_assert(comp(height<metre, double>(2. * m) / (3 * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, double>(2. / 3)));
static_assert(same((2 * m) / height<metre, int>(3 * m),
static_assert(comp((2 * m) / height<metre, int>(3 * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, int>(0)));
static_assert(same((2 * m) / height<metre, double>(3. * m),
static_assert(comp((2 * m) / height<metre, double>(3. * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, double>(2 / 3.)));
static_assert(same((2. * m) / height<metre, int>(3 * m),
static_assert(comp((2. * m) / height<metre, int>(3 * m),
quantity_kind<downcast_kind<height_kind, dim_one>, one, double>(2. / 3)));
static_assert(same(width<metre, int>(8 * m) / width<metre, int>(2 * m),
static_assert(comp(width<metre, int>(8 * m) / width<metre, int>(2 * m),
quantity_kind<downcast_kind<width_kind, dim_one>, one, int>(4)));
static_assert(same(width<metre, int>(8 * m) / width<metre, double>(2 * m),
static_assert(comp(width<metre, int>(8 * m) / width<metre, double>(2 * m),
quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(4.0)));
static_assert(same(width<metre, double>(8 * m) / width<metre, int>(2 * m),
static_assert(comp(width<metre, double>(8 * m) / width<metre, int>(2 * m),
quantity_kind<downcast_kind<width_kind, dim_one>, one, double>(4.0)));
static_assert(same(apples<one, int>(8) / apples<one, int>(2), apples<one, int>(4)));
static_assert(same(apples<one, int>(8) / (2 / apples<one, int>(1)), apples<one, int>(4)));
static_assert(comp(apples<one, int>(8) / apples<one, int>(2), apples<one, int>(4)));
static_assert(comp(apples<one, int>(8) / (2 / apples<one, int>(1)), apples<one, int>(4)));
static_assert(same(horizontal_area<square_metre>(8 * (m * m)) / width<metre>(2 * m), width<metre>(4 * m)));
static_assert(same(horizontal_area<square_metre>(4 * (m * m)) / (1 * m), width<metre>(4 * m)));
static_assert(comp(horizontal_area<square_metre>(8 * (m * m)) / width<metre>(2 * m), width<metre>(4 * m)));
static_assert(comp(horizontal_area<square_metre>(4 * (m * m)) / (1 * m), width<metre>(4 * m)));
static_assert(same(width<metre, int>(2 * m) % 3, width<metre, int>(2 * m)));
static_assert(same(width<metre, int>(3 * m) % width<metre, int>(2 * m), width<metre, int>(1 * m)));
@ -800,7 +800,7 @@ static_assert(same(quantity_kind_cast<cgs_width_kind>(width<centimetre, int>(1 *
static_assert(same(quantity_kind_cast<cgs_width_kind, cgs::centimetre>(width<centimetre, int>(1 * cm)), cgs_width<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_kind_cast<cgs_width_kind>(width<metre, int>(1 * m)), cgs_width<metre, int>(1 * m)));
static_assert(same(quantity_kind_cast<cgs_width_kind, metre>(width<metre, int>(1 * m)), cgs_width<metre, int>(1 * m)));
static_assert(same(quantity_kind_cast<cgs::dim_length>(width<centimetre, int>(1 * cm)), width<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(comp(quantity_kind_cast<cgs::dim_length>(width<centimetre, int>(1 * cm)), width<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_kind_cast<length<kilometre, int>>(width<metre, int>(1 * m)), width<kilometre, int>(0 * km)));
static_assert(same(quantity_kind_cast<length<centimetre, int>>(width<metre, int>(1 * m)), width<centimetre, int>(100 * cm)));
static_assert(same(quantity_kind_cast<length<centimetre, int>>(width<metre, double>(0.01 * m)), width<centimetre, int>(1 * cm)));

View File

@ -250,7 +250,7 @@ static_assert(abscissa<metre>{}.relative().common() == 0 * m);
// CTAD
/////////
static_assert(same(quantity_point_kind(width<metre, int>(0 * m)), abscissa<metre, int>{}));
static_assert(comp(quantity_point_kind(width<metre, int>(0 * m)), abscissa<metre, int>{}));
static_assert(same(quantity_point_kind(abscissa<metre, int>(0 * m)), abscissa<metre, int>{}));
@ -500,16 +500,16 @@ static_assert(invalid_compound_assignments_<time_point_kind, second, std::chrono
/////////////////////////
// clang-format off
static_assert(same(abscissa<metre, int>(2 * m) + width<metre, int>(3 * m), abscissa<metre, int>(5 * m)));
static_assert(same(abscissa<metre, int>(2 * m) + width<metre, double>(3. * m), abscissa<metre, double>(5. * m)));
static_assert(same(abscissa<metre, double>(2. * m) + width<metre, int>(3 * m), abscissa<metre, double>(5. * m)));
static_assert(same(abscissa<kilometre, int>(2 * km) + width<metre, double>(3e3 * m), abscissa<metre, double>(5e3 * m)));
static_assert(same(abscissa<metre, double>(2e3 * m) + width<kilometre, int>(3 * km), abscissa<metre, double>(5e3 * m)));
static_assert(same(width<metre, int>(2 * m) + abscissa<metre, int>(3 * m), abscissa<metre, int>(5 * m)));
static_assert(same(width<metre, int>(2 * m) + abscissa<metre, double>(3. * m), abscissa<metre, double>(5. * m)));
static_assert(same(width<metre, double>(2. * m) + abscissa<metre, int>(3 * m), abscissa<metre, double>(5. * m)));
static_assert(same(width<kilometre, int>(2 * km) + abscissa<metre, double>(3e3 * m), abscissa<metre, double>(5e3 * m)));
static_assert(same(width<metre, double>(2e3 * m) + abscissa<kilometre, int>(3 * km), abscissa<metre, double>(5e3 * m)));
static_assert(comp(abscissa<metre, int>(2 * m) + width<metre, int>(3 * m), abscissa<metre, int>(5 * m)));
static_assert(comp(abscissa<metre, int>(2 * m) + width<metre, double>(3. * m), abscissa<metre, double>(5. * m)));
static_assert(comp(abscissa<metre, double>(2. * m) + width<metre, int>(3 * m), abscissa<metre, double>(5. * m)));
static_assert(comp(abscissa<kilometre, int>(2 * km) + width<metre, double>(3e3 * m), abscissa<metre, double>(5e3 * m)));
static_assert(comp(abscissa<metre, double>(2e3 * m) + width<kilometre, int>(3 * km), abscissa<metre, double>(5e3 * m)));
static_assert(comp(width<metre, int>(2 * m) + abscissa<metre, int>(3 * m), abscissa<metre, int>(5 * m)));
static_assert(comp(width<metre, int>(2 * m) + abscissa<metre, double>(3. * m), abscissa<metre, double>(5. * m)));
static_assert(comp(width<metre, double>(2. * m) + abscissa<metre, int>(3 * m), abscissa<metre, double>(5. * m)));
static_assert(comp(width<kilometre, int>(2 * km) + abscissa<metre, double>(3e3 * m), abscissa<metre, double>(5e3 * m)));
static_assert(comp(width<metre, double>(2e3 * m) + abscissa<kilometre, int>(3 * km), abscissa<metre, double>(5e3 * m)));
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, double>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
@ -522,16 +522,16 @@ static_assert(!std::is_invocable_v<std::plus<>, quantity_point<dynamic_origin<di
static_assert(!std::is_invocable_v<std::plus<>, length<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, double, abscissa<metre>>);
static_assert(same(abscissa<metre, int>(2 * m) - width<metre, int>(3 * m), abscissa<metre, int>(-1 * m)));
static_assert(same(abscissa<metre, int>(2 * m) - width<metre, double>(3. * m), abscissa<metre, double>(-1. * m)));
static_assert(same(abscissa<metre, double>(2. * m) - width<metre, int>(3 * m), abscissa<metre, double>(-1. * m)));
static_assert(same(abscissa<kilometre, int>(2 * km) - width<metre, double>(3e3 * m), abscissa<metre, double>(-1e3 * m)));
static_assert(same(abscissa<metre, double>(2e3 * m) - width<kilometre, int>(3 * km), abscissa<metre, double>(-1e3 * m)));
static_assert(comp(abscissa<metre, int>(2 * m) - width<metre, int>(3 * m), abscissa<metre, int>(-1 * m)));
static_assert(comp(abscissa<metre, int>(2 * m) - width<metre, double>(3. * m), abscissa<metre, double>(-1. * m)));
static_assert(comp(abscissa<metre, double>(2. * m) - width<metre, int>(3 * m), abscissa<metre, double>(-1. * m)));
static_assert(comp(abscissa<kilometre, int>(2 * km) - width<metre, double>(3e3 * m), abscissa<metre, double>(-1e3 * m)));
static_assert(comp(abscissa<metre, double>(2e3 * m) - width<kilometre, int>(3 * km), abscissa<metre, double>(-1e3 * m)));
static_assert(same(abscissa<metre, int>(2 * m) - abscissa<metre, int>(3 * m), width<metre, int>(-1 * m)));
static_assert(same(abscissa<metre, int>(2 * m) - abscissa<metre, double>(3. * m), width<metre, double>(-1. * m)));
static_assert(same(abscissa<metre, double>(2. * m) - abscissa<metre, int>(3 * m), width<metre, double>(-1. * m)));
static_assert(same(abscissa<kilometre, int>(2 * km) - abscissa<metre, double>(3e3 * m), width<metre, double>(-1e3 * m)));
static_assert(same(abscissa<metre, double>(2e3 * m) - abscissa<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
static_assert(comp(abscissa<kilometre, int>(2 * km) - abscissa<metre, double>(3e3 * m), width<metre, double>(-1e3 * m)));
static_assert(comp(abscissa<metre, double>(2e3 * m) - abscissa<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, double>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
@ -634,41 +634,41 @@ static_assert(same(quantity_point_kind_cast<abscissa<metre, double>>(abscissa<me
static_assert(same(quantity_point_kind_cast<abscissa<kilometre, int>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<abscissa<kilometre, int>>(abscissa<metre, int>(1000 * m)), abscissa<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<abscissa<kilometre, double>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, double>(0.999 * km)));
static_assert(same(quantity_point_kind_cast<width<metre, int>>(abscissa<metre, int>(1 * m)), abscissa<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<width<metre, double>>(abscissa<metre, int>(1 * m)), abscissa<metre, double>(1.0 * m)));
static_assert(same(quantity_point_kind_cast<width<kilometre, int>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<width<kilometre, int>>(abscissa<metre, int>(1000 * m)), abscissa<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<width<kilometre, double>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, double>(0.999 * km)));
static_assert(same(quantity_point_kind_cast<double>(abscissa<metre, int>(1 * m)), abscissa<metre, double>(1.0 * m)));
static_assert(same(quantity_point_kind_cast<metre>(abscissa<metre, int>(1 * m)), abscissa<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<kilometre>(abscissa<metre, int>(999 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<kilometre>(abscissa<metre, int>(1000 * m)), abscissa<kilometre, int>(1 * km)));
static_assert(comp(quantity_point_kind_cast<width<metre, int>>(abscissa<metre, int>(1 * m)), abscissa<metre, int>(1 * m)));
static_assert(comp(quantity_point_kind_cast<width<metre, double>>(abscissa<metre, int>(1 * m)), abscissa<metre, double>(1.0 * m)));
static_assert(comp(quantity_point_kind_cast<width<kilometre, int>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(comp(quantity_point_kind_cast<width<kilometre, int>>(abscissa<metre, int>(1000 * m)), abscissa<kilometre, int>(1 * km)));
static_assert(comp(quantity_point_kind_cast<width<kilometre, double>>(abscissa<metre, int>(999 * m)), abscissa<kilometre, double>(0.999 * km)));
static_assert(comp(quantity_point_kind_cast<double>(abscissa<metre, int>(1 * m)), abscissa<metre, double>(1.0 * m)));
static_assert(comp(quantity_point_kind_cast<metre>(abscissa<metre, int>(1 * m)), abscissa<metre, int>(1 * m)));
static_assert(comp(quantity_point_kind_cast<kilometre>(abscissa<metre, int>(999 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(comp(quantity_point_kind_cast<kilometre>(abscissa<metre, int>(1000 * m)), abscissa<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<ordinate<metre, int>>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<ordinate<metre, double>>(abscissa<metre, int>(1 * m)), ordinate<metre, double>(1.0 * m)));
static_assert(same(quantity_point_kind_cast<ordinate<kilometre, int>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<ordinate<kilometre, int>>(abscissa<metre, int>(1000 * m)), ordinate<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<ordinate<kilometre, double>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, double>(0.999 * km)));
static_assert(same(quantity_point_kind_cast<height<metre, int>>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<height<metre, double>>(abscissa<metre, int>(1 * m)), ordinate<metre, double>(1.0 * m)));
static_assert(same(quantity_point_kind_cast<height<kilometre, int>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<height<kilometre, int>>(abscissa<metre, int>(1000 * m)), ordinate<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<height<kilometre, double>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, double>(0.999 * km)));
static_assert(same(quantity_point_kind_cast<height_kind>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(comp(quantity_point_kind_cast<height<metre, int>>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(comp(quantity_point_kind_cast<height<metre, double>>(abscissa<metre, int>(1 * m)), ordinate<metre, double>(1.0 * m)));
static_assert(comp(quantity_point_kind_cast<height<kilometre, int>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, int>(0 * km)));
static_assert(comp(quantity_point_kind_cast<height<kilometre, int>>(abscissa<metre, int>(1000 * m)), ordinate<kilometre, int>(1 * km)));
static_assert(comp(quantity_point_kind_cast<height<kilometre, double>>(abscissa<metre, int>(999 * m)), ordinate<kilometre, double>(0.999 * km)));
static_assert(comp(quantity_point_kind_cast<height_kind>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<ordinate_kind, metre>(abscissa<metre, int>(1 * m)), ordinate<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<ordinate_kind, kilometre>(abscissa<metre, int>(999 * m)), ordinate<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<ordinate_kind, kilometre>(abscissa<metre, int>(1000 * m)), ordinate<kilometre, int>(1 * km)));
static_assert(same(quantity_point_kind_cast<cgs_width<cgs::centimetre, int>>(abscissa<centimetre, int>(1 * cm)), quantity_point_kind(cgs_width<cgs::centimetre, int>(1 * cgs_cm))));
static_assert(same(quantity_point_kind_cast<cgs_width_kind>(abscissa<centimetre, int>(1 * cm)), quantity_point_kind(cgs_width<cgs::centimetre, int>(1 * cgs_cm))));
static_assert(same(quantity_point_kind_cast<altitude_kind>(abscissa<centimetre, int>(1 * cm)), altitude<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(comp(quantity_point_kind_cast<altitude_kind>(abscissa<centimetre, int>(1 * cm)), altitude<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_point_kind_cast<altitude_kind, cgs::centimetre>(abscissa<centimetre, int>(1 * cm)), altitude<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_point_kind_cast<cgs_width_kind>(abscissa<metre, int>(1 * m)), quantity_point_kind(cgs_width<metre, int>(1 * m))));
static_assert(same(quantity_point_kind_cast<altitude_kind>(abscissa<metre, int>(1 * m)), altitude<metre, int>(1 * m)));
static_assert(comp(quantity_point_kind_cast<altitude_kind>(abscissa<metre, int>(1 * m)), altitude<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<altitude_kind, metre>(abscissa<metre, int>(1 * m)), altitude<metre, int>(1 * m)));
static_assert(same(quantity_point_kind_cast<cgs::dim_length>(abscissa<centimetre, int>(1 * cm)), abscissa<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_point_kind_cast<length<kilometre, int>>(abscissa<metre, int>(1 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, int>(1 * m)), abscissa<centimetre, int>(100 * cm)));
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, double>(0.01 * m)), abscissa<centimetre, int>(1 * cm)));
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<cgs::centimetre, int>(1 * cgs_cm)), abscissa<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(comp(quantity_point_kind_cast<cgs::dim_length>(abscissa<centimetre, int>(1 * cm)), abscissa<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(comp(quantity_point_kind_cast<length<kilometre, int>>(abscissa<metre, int>(1 * m)), abscissa<kilometre, int>(0 * km)));
static_assert(comp(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, int>(1 * m)), abscissa<centimetre, int>(100 * cm)));
static_assert(comp(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, double>(0.01 * m)), abscissa<centimetre, int>(1 * cm)));
static_assert(comp(quantity_point_kind_cast<length<centimetre, int>>(abscissa<cgs::centimetre, int>(1 * cgs_cm)), abscissa<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_point_kind_cast<screen_si_cgs_width<metre, int>>(screen_si_width<metre, int>(1 * m)), screen_si_cgs_width<metre, int>(1 * m)));
// clang-format on
template<typename Int>

View File

@ -427,11 +427,11 @@ static_assert(invalid_binary_operations<metre>);
static_assert(is_same_v<decltype(1_q_m + 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m - 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m * 1), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m * quantity{1}), length<metre, std::int64_t>>);
static_assert(compare<decltype(1_q_m * quantity{1}), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1 * 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(quantity{1} * 1_q_m), length<metre, std::int64_t>>);
static_assert(compare<decltype(quantity{1} * 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m / 1), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m / quantity{1}), length<metre, std::int64_t>>);
static_assert(compare<decltype(1_q_m / quantity{1}), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m % 1), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m % quantity{1}), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_m % 1_q_m), length<metre, std::int64_t>>);
@ -458,10 +458,10 @@ static_assert(is_same_v<decltype(1_q_m + 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m - 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m * 1.L), length<metre, long double>>); // TODO should we address fundamental types implicit truncating conversions with concepts?
static_assert(is_same_v<decltype(1 * 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m * quantity{1.L}), length<metre, long double>>); // TODO should we address fundamental types implicit truncating conversions with concepts?
static_assert(is_same_v<decltype(quantity{1} * 1._q_m), length<metre, long double>>);
static_assert(compare<decltype(1_q_m * quantity{1.L}), length<metre, long double>>); // TODO should we address fundamental types implicit truncating conversions with concepts?
static_assert(compare<decltype(quantity{1} * 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m / 1.L), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m / quantity{1.L}), length<metre, long double>>);
static_assert(compare<decltype(1_q_m / quantity{1.L}), length<metre, long double>>);
static_assert(compare<decltype(1_q_m * dimensionless<percent, long double>(1)), length<centimetre, long double>>);
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) * 1._q_m), length<centimetre, long double>>);
static_assert(compare<decltype(1_q_m * 1._q_m), area<square_metre, long double>>);
@ -479,10 +479,10 @@ static_assert(is_same_v<decltype(1._q_m + 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m - 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m * 1), length<metre, long double>>);
static_assert(is_same_v<decltype(1.L * 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m * quantity{1}), length<metre, long double>>);
static_assert(is_same_v<decltype(quantity{1.L} * 1_q_m), length<metre, long double>>);
static_assert(compare<decltype(1._q_m * quantity{1}), length<metre, long double>>);
static_assert(compare<decltype(quantity{1.L} * 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m / 1), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m / quantity{1}), length<metre, long double>>);
static_assert(compare<decltype(1._q_m / quantity{1}), length<metre, long double>>);
static_assert(compare<decltype(1._q_m * dimensionless<percent, std::int64_t>(1)), length<centimetre, long double>>);
static_assert(compare<decltype(dimensionless<percent, long double>(1) * 1_q_m), length<centimetre, long double>>);
static_assert(compare<decltype(1._q_m / dimensionless<percent, std::int64_t>(1)), length<hectometre, long double>>);
@ -493,25 +493,25 @@ static_assert(compare<decltype(quantity{1.L} / 1_q_s), frequency<hertz, long dou
static_assert(compare<decltype(dimensionless<percent, long double>(1) / 1_q_s), frequency<scaled_unit<ratio(1, 100), hertz>, long double>>);
// different units
static_assert(is_same_v<decltype(1_q_m + 1_q_km), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1._q_m + 1_q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m + 1._q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m + 1._q_km), length<metre, long double>>);
static_assert(compare<decltype(1_q_m + 1_q_km), length<metre, std::int64_t>>);
static_assert(compare<decltype(1._q_m + 1_q_km), length<metre, long double>>);
static_assert(compare<decltype(1_q_m + 1._q_km), length<metre, long double>>);
static_assert(compare<decltype(1._q_m + 1._q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_km + 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1._q_km + 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_km + 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_km + 1._q_m), length<metre, long double>>);
static_assert(compare<decltype(1_q_km + 1_q_m), length<metre, std::int64_t>>);
static_assert(compare<decltype(1._q_km + 1_q_m), length<metre, long double>>);
static_assert(compare<decltype(1_q_km + 1._q_m), length<metre, long double>>);
static_assert(compare<decltype(1._q_km + 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m - 1_q_km), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1._q_m - 1_q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m - 1._q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_m - 1._q_km), length<metre, long double>>);
static_assert(compare<decltype(1_q_m - 1_q_km), length<metre, std::int64_t>>);
static_assert(compare<decltype(1._q_m - 1_q_km), length<metre, long double>>);
static_assert(compare<decltype(1_q_m - 1._q_km), length<metre, long double>>);
static_assert(compare<decltype(1._q_m - 1._q_km), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_km - 1_q_m), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1._q_km - 1_q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_km - 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1._q_km - 1._q_m), length<metre, long double>>);
static_assert(compare<decltype(1_q_km - 1_q_m), length<metre, std::int64_t>>);
static_assert(compare<decltype(1._q_km - 1_q_m), length<metre, long double>>);
static_assert(compare<decltype(1_q_km - 1._q_m), length<metre, long double>>);
static_assert(compare<decltype(1._q_km - 1._q_m), length<metre, long double>>);
static_assert(is_same_v<decltype(1_q_m % 1_q_km), length<metre, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_km % 1_q_m), length<kilometre, std::int64_t>>);
@ -820,8 +820,8 @@ static_assert(is_same_v<decltype(1_q_mm + 1_q_km), length<scaled_unit<ratio(1, 1
#else
static_assert(is_same_v<decltype(10_q_m / 5_q_s), speed<metre_per_second, std::int64_t>>);
static_assert(is_same_v<decltype(1_q_mm + 1_q_km), length<millimetre, std::int64_t>>);
static_assert(compare<decltype(10_q_m / 5_q_s), speed<metre_per_second, std::int64_t>>);
static_assert(compare<decltype(1_q_mm + 1_q_km), length<millimetre, std::int64_t>>);
#endif
@ -835,17 +835,17 @@ constexpr auto quotient_remainder_theorem(auto q1, auto q2)
return q;
}
static_assert(same(quotient_remainder_theorem(3'000 * m, 400 * m), 3'000 * m));
static_assert(same(quotient_remainder_theorem(3 * km, 400 * m), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, 2 * m), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, 400'000 * mm), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, 2'000 * mm), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, 400 * mm), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, 2 * mm), 3 * km));
static_assert(comp(quotient_remainder_theorem(3'000 * m, 400 * m), 3'000 * m));
static_assert(comp(quotient_remainder_theorem(3 * km, 400 * m), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, 2 * m), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, 400'000 * mm), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, 2'000 * mm), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, 400 * mm), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, 2 * mm), 3 * km));
static_assert(same(quotient_remainder_theorem(3'000 * m, 400), 3'000 * m));
static_assert(same(quotient_remainder_theorem(3'000 * m, quantity(400)), 3'000 * m));
static_assert(same(quotient_remainder_theorem(3 * km, quantity(400)), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, quantity(2)), 3 * km));
static_assert(same(quotient_remainder_theorem(3 * km, dimensionless<scaled_unit<ratio(1, 1000), one>, int>(400)), 3 * km));
static_assert(comp(quotient_remainder_theorem(3'000 * m, quantity(400)), 3'000 * m));
static_assert(comp(quotient_remainder_theorem(3 * km, quantity(400)), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, quantity(2)), 3 * km));
static_assert(comp(quotient_remainder_theorem(3 * km, dimensionless<scaled_unit<ratio(1, 1000), one>, int>(400)), 3 * km));
} // namespace

View File

@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "test_tools.h"
#include <units/bits/external/hacks.h>
#include <units/bits/external/type_traits.h>
#include <units/isq/si/area.h>
@ -70,8 +71,8 @@ static_assert([] {
const auto duration{2};
return length * km / (duration * h);
}() == 60_q_km_per_h);
static_assert(is_same_v<decltype(std::int64_t{120} * km / (2 * h)), decltype(60_q_km_per_h)>);
static_assert(is_same_v<decltype(120.L * km / (2 * h)), decltype(60._q_km_per_h)>);
static_assert(compare<decltype(std::int64_t{120} * km / (2 * h)), decltype(60_q_km_per_h)>);
static_assert(compare<decltype(120.L * km / (2 * h)), decltype(60._q_km_per_h)>);
static_assert(1. / 4 * m2 == 1._q_m2 / 4);

View File

@ -123,16 +123,9 @@ constexpr bool ctad_constructible_from(Vs...)
return ctad_constructible_from_<T, void, Us..., Vs...>;
}
#if UNITS_DOWNCAST_MODE
constexpr auto same = []<std::equality_comparable T>(T l, T r) { return l == r; };
#else
constexpr auto same = []<typename T, typename U>(T l, U r)
requires requires { l == r; }
// requires std::equality_comparable_with<T, U> // TODO: Fix #205
{
return l == r;
};
#endif
constexpr auto comp = // TODO: Fix #205 to use `std::equality_comparable_with<T> U`.
[]<typename T, typename U>(T l, U r) requires compare<T, U> { return l == r; };
template<auto F>
requires requires { F(); }