mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-31 02:47:16 +02:00
fix: MSVC-related fixes and workarounds
This commit is contained in:
@ -134,11 +134,11 @@ void example()
|
|||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
using namespace mp_units::si::unit_symbols;
|
using namespace mp_units::si::unit_symbols;
|
||||||
|
|
||||||
const auto a = isq::acceleration(measurement{9.8, 0.1} * (m / s2));
|
const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * (m / s2));
|
||||||
const auto t = measurement{1.2, 0.1} * s;
|
const auto time = measurement{1.2, 0.1} * s;
|
||||||
|
|
||||||
const QuantityOf<isq::velocity> auto v = a * t;
|
const QuantityOf<isq::velocity> auto velocity = acceleration * time;
|
||||||
std::cout << a << " * " << t << " = " << v << " = " << v.in(km / h) << '\n';
|
std::cout << acceleration << " * " << time << " = " << velocity << " = " << velocity.in(km / h) << '\n';
|
||||||
|
|
||||||
const auto length = measurement{123., 1.} * m;
|
const auto length = measurement{123., 1.} * m;
|
||||||
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
std::cout << "10 * " << length << " = " << 10 * length << '\n';
|
||||||
|
@ -103,9 +103,9 @@ struct width_checker {
|
|||||||
if (value < 0) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("negative width"));
|
if (value < 0) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("negative width"));
|
||||||
}
|
}
|
||||||
return static_cast<unsigned long long>(value);
|
return static_cast<unsigned long long>(value);
|
||||||
} else {
|
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("width is not integer"));
|
|
||||||
}
|
}
|
||||||
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("width is not integer"));
|
||||||
|
return 0; // should never happen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,9 +118,9 @@ struct precision_checker {
|
|||||||
if (value < 0) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("negative precision"));
|
if (value < 0) MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("negative precision"));
|
||||||
}
|
}
|
||||||
return static_cast<unsigned long long>(value);
|
return static_cast<unsigned long long>(value);
|
||||||
} else {
|
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("precision is not integer"));
|
|
||||||
}
|
}
|
||||||
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("precision is not integer"));
|
||||||
|
return 0; // should never happen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -230,6 +230,7 @@ template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
|||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string"));
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string"));
|
||||||
|
return begin; // should never happen
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
template<std::input_iterator It, std::sentinel_for<It> S, typename IDHandler>
|
||||||
|
@ -58,8 +58,8 @@ template<QuantitySpec A, QuantitySpec B>
|
|||||||
template<QuantitySpec A, QuantitySpec B>
|
template<QuantitySpec A, QuantitySpec B>
|
||||||
[[nodiscard]] consteval auto have_common_base(A a, B b)
|
[[nodiscard]] consteval auto have_common_base(A a, B b)
|
||||||
{
|
{
|
||||||
constexpr int a_length = hierarchy_path_length(A{});
|
constexpr std::size_t a_length = hierarchy_path_length(A{});
|
||||||
constexpr int b_length = hierarchy_path_length(B{});
|
constexpr std::size_t b_length = hierarchy_path_length(B{});
|
||||||
if constexpr (a_length > b_length)
|
if constexpr (a_length > b_length)
|
||||||
return have_common_base_in_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b);
|
return have_common_base_in_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b);
|
||||||
else
|
else
|
||||||
|
@ -142,7 +142,8 @@ public:
|
|||||||
quantity_point& operator=(quantity_point&&) = default;
|
quantity_point& operator=(quantity_point&&) = default;
|
||||||
|
|
||||||
template<PointOriginFor<quantity_spec> NewPO>
|
template<PointOriginFor<quantity_spec> NewPO>
|
||||||
[[nodiscard]] constexpr QuantityPointOf<NewPO{}> auto point_for(NewPO new_origin) const
|
[[nodiscard]] constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(QuantityPointOf<NewPO{}>) auto point_for(
|
||||||
|
NewPO new_origin) const
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<NewPO, std::remove_const_t<decltype(point_origin)>>)
|
if constexpr (is_same_v<NewPO, std::remove_const_t<decltype(point_origin)>>)
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -41,12 +41,12 @@ namespace detail {
|
|||||||
|
|
||||||
template<QuantitySpec QS, Unit U>
|
template<QuantitySpec QS, Unit U>
|
||||||
requires(!AssociatedUnit<U>) || UnitOf<U, QS{}>
|
requires(!AssociatedUnit<U>) || UnitOf<U, QS{}>
|
||||||
[[nodiscard]] consteval Reference auto make_reference(QS qs, U u)
|
[[nodiscard]] consteval Reference auto make_reference(QS, U u)
|
||||||
{
|
{
|
||||||
if constexpr (detail::QuantityKindSpec<QS>)
|
if constexpr (detail::QuantityKindSpec<QS>)
|
||||||
return u;
|
return u;
|
||||||
else
|
else
|
||||||
return reference<qs, u>{};
|
return reference<QS{}, U{}>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO revise the note in the below comment
|
// TODO revise the note in the below comment
|
||||||
@ -494,9 +494,10 @@ template<QuantitySpec auto... From, QuantitySpec Q>
|
|||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto operator*(QuantitySpec auto lhs, QuantitySpec auto rhs)
|
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||||
|
[[nodiscard]] consteval QuantitySpec auto operator*(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
return clone_kind_of<lhs, rhs>(
|
return clone_kind_of<Lhs{}, Rhs{}>(
|
||||||
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
detail::expr_multiply<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||||
remove_kind(lhs), remove_kind(rhs)));
|
remove_kind(lhs), remove_kind(rhs)));
|
||||||
}
|
}
|
||||||
@ -504,15 +505,16 @@ template<QuantitySpec auto... From, QuantitySpec Q>
|
|||||||
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
template<QuantitySpec Lhs, QuantitySpec Rhs>
|
||||||
[[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
|
[[nodiscard]] consteval QuantitySpec auto operator/(Lhs lhs, Rhs rhs)
|
||||||
{
|
{
|
||||||
return clone_kind_of<lhs, rhs>(
|
return clone_kind_of<Lhs{}, Rhs{}>(
|
||||||
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
detail::expr_divide<derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||||
remove_kind(lhs), remove_kind(rhs)));
|
remove_kind(lhs), remove_kind(rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto operator/(int value, QuantitySpec auto q)
|
template<QuantitySpec QS>
|
||||||
|
[[nodiscard]] consteval QuantitySpec auto operator/(int value, QS qs)
|
||||||
{
|
{
|
||||||
gsl_Expects(value == 1);
|
gsl_Expects(value == 1);
|
||||||
return clone_kind_of<q>(detail::expr_invert<derived_quantity_spec, struct dimensionless>(q));
|
return clone_kind_of<QS{}>(detail::expr_invert<derived_quantity_spec, struct dimensionless>(qs));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto operator/(QuantitySpec auto, int) = delete;
|
[[nodiscard]] consteval QuantitySpec auto operator/(QuantitySpec auto, int) = delete;
|
||||||
@ -554,7 +556,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
|||||||
// `2 * one * (2 * one)` should compare to `4 * one`
|
// `2 * one * (2 * one)` should compare to `4 * one`
|
||||||
// `2 * rad * (2 * rad)` should compare to `4 * rad^2`
|
// `2 * rad * (2 * rad)` should compare to `4 * rad^2`
|
||||||
// all are dimensionless quantities :-(
|
// all are dimensionless quantities :-(
|
||||||
if constexpr (Num == 0 || q == dimensionless)
|
if constexpr (Num == 0 || Q{} == dimensionless)
|
||||||
return dimensionless;
|
return dimensionless;
|
||||||
else if constexpr (ratio{Num, Den} == 1)
|
else if constexpr (ratio{Num, Den} == 1)
|
||||||
return q;
|
return q;
|
||||||
@ -779,7 +781,7 @@ template<int Complexity, QuantitySpec Q>
|
|||||||
template<int Complexity, IntermediateDerivedQuantitySpec Q>
|
template<int Complexity, IntermediateDerivedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(q);
|
constexpr auto c = get_complexity(Q{});
|
||||||
if constexpr (c > Complexity)
|
if constexpr (c > Complexity)
|
||||||
return explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
return explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
||||||
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{});
|
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{});
|
||||||
@ -790,9 +792,9 @@ template<int Complexity, IntermediateDerivedQuantitySpec Q>
|
|||||||
template<int Complexity, NamedQuantitySpec Q>
|
template<int Complexity, NamedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(q);
|
constexpr auto c = get_complexity(Q{});
|
||||||
if constexpr (c > Complexity && requires { Q::_equation_; }) {
|
if constexpr (c > Complexity && requires { Q::_equation_; }) {
|
||||||
constexpr auto res = explode_to_equation(q);
|
constexpr auto res = explode_to_equation(Q{});
|
||||||
return explode<Complexity>(res.equation).common_convertibility_with(res);
|
return explode<Complexity>(res.equation).common_convertibility_with(res);
|
||||||
} else
|
} else
|
||||||
return explode_result{q};
|
return explode_result{q};
|
||||||
@ -887,8 +889,8 @@ extract_results(bool, From = {}, To = {}, prepend_rest = {}, Elem = {}) -> extra
|
|||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
[[nodiscard]] consteval auto extract_convertible_quantities(From from, To to)
|
[[nodiscard]] consteval auto extract_convertible_quantities(From from, To to)
|
||||||
{
|
{
|
||||||
constexpr auto qfrom = map_power(from);
|
constexpr auto qfrom = map_power(From{});
|
||||||
constexpr auto qto = map_power(to);
|
constexpr auto qto = map_power(To{});
|
||||||
if constexpr (qfrom.dimension == qto.dimension) {
|
if constexpr (qfrom.dimension == qto.dimension) {
|
||||||
if constexpr (is_specialization_of_power<From> && is_specialization_of_power<To>) {
|
if constexpr (is_specialization_of_power<From> && is_specialization_of_power<To>) {
|
||||||
constexpr auto cr = common_ratio(From::exponent, To::exponent);
|
constexpr auto cr = common_ratio(From::exponent, To::exponent);
|
||||||
@ -905,8 +907,8 @@ template<typename From, typename To>
|
|||||||
else
|
else
|
||||||
return std::tuple{Q{}, ratio{1}};
|
return std::tuple{Q{}, ratio{1}};
|
||||||
};
|
};
|
||||||
constexpr auto from_norm = normalize(from);
|
constexpr auto from_norm = normalize(From{});
|
||||||
constexpr auto to_norm = normalize(to);
|
constexpr auto to_norm = normalize(To{});
|
||||||
constexpr auto from_factor = std::get<0>(from_norm);
|
constexpr auto from_factor = std::get<0>(from_norm);
|
||||||
constexpr auto from_exp = std::get<1>(from_norm);
|
constexpr auto from_exp = std::get<1>(from_norm);
|
||||||
constexpr auto to_factor = std::get<0>(to_norm);
|
constexpr auto to_factor = std::get<0>(to_norm);
|
||||||
@ -1335,11 +1337,11 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
|
|
||||||
if constexpr (From::dimension != To::dimension)
|
if constexpr (From::dimension != To::dimension)
|
||||||
return no;
|
return no;
|
||||||
else if constexpr (from == to)
|
else if constexpr (From{} == To{})
|
||||||
return yes;
|
return yes;
|
||||||
else if constexpr (QuantityKindSpec<From> || QuantityKindSpec<To>) {
|
else if constexpr (QuantityKindSpec<From> || QuantityKindSpec<To>) {
|
||||||
constexpr auto from_kind = get_kind(from);
|
constexpr auto from_kind = get_kind(From{});
|
||||||
constexpr auto to_kind = get_kind(to);
|
constexpr auto to_kind = get_kind(To{});
|
||||||
constexpr auto exploded_kind_result = [](specs_convertible_result res) {
|
constexpr auto exploded_kind_result = [](specs_convertible_result res) {
|
||||||
using enum specs_convertible_result;
|
using enum specs_convertible_result;
|
||||||
return res == no ? no : yes;
|
return res == no ? no : yes;
|
||||||
@ -1354,21 +1356,21 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
else
|
else
|
||||||
return exploded_kind_result(
|
return exploded_kind_result(
|
||||||
convertible_impl(from_kind, get_kind(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
convertible_impl(from_kind, get_kind(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
||||||
} else if constexpr (NestedQuantityKindSpecOf<get_kind(to), from> && get_kind(to) == to)
|
} else if constexpr (NestedQuantityKindSpecOf<get_kind(To{}), from> && get_kind(To{}) == To{})
|
||||||
return yes;
|
return yes;
|
||||||
else if constexpr (NamedQuantitySpec<From> && NamedQuantitySpec<To>) {
|
else if constexpr (NamedQuantitySpec<From> && NamedQuantitySpec<To>) {
|
||||||
if constexpr (have_common_base(from, to)) {
|
if constexpr (have_common_base(From{}, To{})) {
|
||||||
if (std::derived_from<From, To>)
|
if (std::derived_from<From, To>)
|
||||||
return yes;
|
return yes;
|
||||||
else
|
else
|
||||||
return std::derived_from<To, From> ? explicit_conversion : (get_kind(from) == get_kind(to) ? cast : no);
|
return std::derived_from<To, From> ? explicit_conversion : (get_kind(from) == get_kind(to) ? cast : no);
|
||||||
} else if constexpr (get_kind(from) != get_kind(to))
|
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
||||||
return no;
|
return no;
|
||||||
else if constexpr (get_complexity(from) != get_complexity(to)) {
|
else if constexpr (get_complexity(From{}) != get_complexity(To{})) {
|
||||||
if constexpr (get_complexity(from) > get_complexity(to))
|
if constexpr (get_complexity(From{}) > get_complexity(To{}))
|
||||||
return convertible_impl(explode<get_complexity(to)>(from).quantity, to);
|
return convertible_impl(explode<get_complexity(to)>(from).quantity, to);
|
||||||
else {
|
else {
|
||||||
constexpr auto res = explode<get_complexity(from)>(to);
|
auto res = explode<get_complexity(from)>(to);
|
||||||
return min(res.result, convertible_impl(from, res.quantity));
|
return min(res.result, convertible_impl(from, res.quantity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1379,7 +1381,7 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
if constexpr (NamedQuantitySpec<std::remove_const_t<decltype(res.quantity)>>)
|
if constexpr (NamedQuantitySpec<std::remove_const_t<decltype(res.quantity)>>)
|
||||||
return convertible_impl(res.quantity, to);
|
return convertible_impl(res.quantity, to);
|
||||||
else if constexpr (requires { to._equation_; }) {
|
else if constexpr (requires { to._equation_; }) {
|
||||||
constexpr auto eq = explode_to_equation(to);
|
auto eq = explode_to_equation(to);
|
||||||
return min(eq.result, convertible_impl(res.quantity, eq.equation));
|
return min(eq.result, convertible_impl(res.quantity, eq.equation));
|
||||||
} else
|
} else
|
||||||
return are_ingredients_convertible(from, to);
|
return are_ingredients_convertible(from, to);
|
||||||
@ -1449,16 +1451,16 @@ template<QuantitySpec Q>
|
|||||||
template<QuantitySpec Q>
|
template<QuantitySpec Q>
|
||||||
[[nodiscard]] consteval QuantitySpec auto get_kind(Q q)
|
[[nodiscard]] consteval QuantitySpec auto get_kind(Q q)
|
||||||
{
|
{
|
||||||
auto defined_as_kind = [](auto qq) {
|
auto defined_as_kind = []<typename QQ>(QQ qq) {
|
||||||
if constexpr (requires { detail::defined_as_kind(qq); })
|
if constexpr (requires { detail::defined_as_kind(qq); })
|
||||||
return detail::defined_as_kind(qq);
|
return detail::defined_as_kind(QQ{});
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if constexpr (detail::QuantityKindSpec<Q>) {
|
if constexpr (detail::QuantityKindSpec<Q>) {
|
||||||
return remove_kind(q);
|
return remove_kind(q);
|
||||||
} else if constexpr (defined_as_kind(q)) {
|
} else if constexpr (defined_as_kind(Q{})) {
|
||||||
return q;
|
return q;
|
||||||
} else if constexpr (requires { Q::_parent_; }) {
|
} else if constexpr (requires { Q::_parent_; }) {
|
||||||
return get_kind(Q::_parent_);
|
return get_kind(Q::_parent_);
|
||||||
@ -1481,25 +1483,25 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
|||||||
using QQ2 = std::remove_const_t<decltype(remove_kind(q2))>;
|
using QQ2 = std::remove_const_t<decltype(remove_kind(q2))>;
|
||||||
if constexpr (is_same_v<Q1, Q2>)
|
if constexpr (is_same_v<Q1, Q2>)
|
||||||
return q1;
|
return q1;
|
||||||
else if constexpr (detail::NestedQuantityKindSpecOf<q1, q2>)
|
else if constexpr (detail::NestedQuantityKindSpecOf<Q1{}, Q2{}>)
|
||||||
return remove_kind(q1);
|
return remove_kind(q1);
|
||||||
else if constexpr (detail::NestedQuantityKindSpecOf<q2, q1>)
|
else if constexpr (detail::NestedQuantityKindSpecOf<Q2{}, Q1{}>)
|
||||||
return remove_kind(q2);
|
return remove_kind(q2);
|
||||||
else if constexpr ((detail::QuantityKindSpec<Q1> && !detail::QuantityKindSpec<Q2>) ||
|
else if constexpr ((detail::QuantityKindSpec<Q1> && !detail::QuantityKindSpec<Q2>) ||
|
||||||
(detail::IntermediateDerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
(detail::IntermediateDerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
||||||
implicitly_convertible(q1, q2)))
|
implicitly_convertible(Q1{}, Q2{})))
|
||||||
return q2;
|
return q2;
|
||||||
else if constexpr ((!detail::QuantityKindSpec<Q1> && detail::QuantityKindSpec<Q2>) ||
|
else if constexpr ((!detail::QuantityKindSpec<Q1> && detail::QuantityKindSpec<Q2>) ||
|
||||||
(detail::NamedQuantitySpec<QQ1> && detail::IntermediateDerivedQuantitySpec<QQ2> &&
|
(detail::NamedQuantitySpec<QQ1> && detail::IntermediateDerivedQuantitySpec<QQ2> &&
|
||||||
implicitly_convertible(q2, q1)))
|
implicitly_convertible(Q2{}, Q1{})))
|
||||||
return q1;
|
return q1;
|
||||||
else if constexpr (detail::have_common_base(q1, q2))
|
else if constexpr (detail::have_common_base(Q1{}, Q2{}))
|
||||||
return detail::get_common_base(q1, q2);
|
return detail::get_common_base(q1, q2);
|
||||||
else if constexpr (implicitly_convertible(q1, q2))
|
else if constexpr (implicitly_convertible(Q1{}, Q2{}))
|
||||||
return q2;
|
return q2;
|
||||||
else if constexpr (implicitly_convertible(q2, q1))
|
else if constexpr (implicitly_convertible(Q2{}, Q1{}))
|
||||||
return q1;
|
return q1;
|
||||||
else if constexpr (implicitly_convertible(get_kind(q1), get_kind(q2)))
|
else if constexpr (implicitly_convertible(get_kind(Q1{}), get_kind(Q2{})))
|
||||||
return get_kind(q2);
|
return get_kind(q2);
|
||||||
else
|
else
|
||||||
return get_kind(q1);
|
return get_kind(q1);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <mp-units/bits/external/hacks.h>
|
||||||
#include <mp-units/bits/get_associated_quantity.h>
|
#include <mp-units/bits/get_associated_quantity.h>
|
||||||
#include <mp-units/bits/quantity_concepts.h>
|
#include <mp-units/bits/quantity_concepts.h>
|
||||||
#include <mp-units/bits/reference_concepts.h>
|
#include <mp-units/bits/reference_concepts.h>
|
||||||
@ -73,13 +74,21 @@ struct reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U2>
|
template<AssociatedUnit U2>
|
||||||
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
[[nodiscard]] friend consteval decltype(reference<Q * get_quantity_spec(U2{}), U * U2{}>{}) operator*(reference, U2)
|
||||||
|
#else
|
||||||
[[nodiscard]] friend consteval reference<Q * get_quantity_spec(U2{}), U * U2{}> operator*(reference, U2)
|
[[nodiscard]] friend consteval reference<Q * get_quantity_spec(U2{}), U * U2{}> operator*(reference, U2)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U1>
|
template<AssociatedUnit U1>
|
||||||
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
[[nodiscard]] friend consteval decltype(reference<get_quantity_spec(U1{}) * Q, U1{} * U>{}) operator*(U1, reference)
|
||||||
|
#else
|
||||||
[[nodiscard]] friend consteval reference<get_quantity_spec(U1{}) * Q, U1{} * U> operator*(U1, reference)
|
[[nodiscard]] friend consteval reference<get_quantity_spec(U1{}) * Q, U1{} * U> operator*(U1, reference)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -91,13 +100,21 @@ struct reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U2>
|
template<AssociatedUnit U2>
|
||||||
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
[[nodiscard]] friend consteval decltype(reference<Q / get_quantity_spec(U2{}), U / U2{}>{}) operator/(reference, U2)
|
||||||
|
#else
|
||||||
[[nodiscard]] friend consteval reference<Q / get_quantity_spec(U2{}), U / U2{}> operator/(reference, U2)
|
[[nodiscard]] friend consteval reference<Q / get_quantity_spec(U2{}), U / U2{}> operator/(reference, U2)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U1>
|
template<AssociatedUnit U1>
|
||||||
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
[[nodiscard]] friend consteval decltype(reference<get_quantity_spec(U1{}) / Q, U1{} / U>{}) operator/(U1, reference)
|
||||||
|
#else
|
||||||
[[nodiscard]] friend consteval reference<get_quantity_spec(U1{}) / Q, U1{} / U> operator/(U1, reference)
|
[[nodiscard]] friend consteval reference<get_quantity_spec(U1{}) / Q, U1{} / U> operator/(U1, reference)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <mp-units/bits/external/hacks.h>
|
||||||
#include <mp-units/quantity_spec.h>
|
#include <mp-units/quantity_spec.h>
|
||||||
#include <mp-units/reference.h>
|
#include <mp-units/reference.h>
|
||||||
#include <mp-units/unit.h>
|
#include <mp-units/unit.h>
|
||||||
@ -63,7 +64,11 @@ struct system_reference {
|
|||||||
|
|
||||||
template<Unit U>
|
template<Unit U>
|
||||||
requires(convertible(coherent_unit, U{}))
|
requires(convertible(coherent_unit, U{}))
|
||||||
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
[[nodiscard]] constexpr decltype(reference<quantity_spec, U{}>{}) operator[](U) const
|
||||||
|
#else
|
||||||
[[nodiscard]] constexpr reference<quantity_spec, U{}> operator[](U) const
|
[[nodiscard]] constexpr reference<quantity_spec, U{}> operator[](U) const
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -354,9 +354,9 @@ template<typename T, typename F, int Num, int... Den>
|
|||||||
template<typename... Us>
|
template<typename... Us>
|
||||||
[[nodiscard]] consteval auto get_canonical_unit_impl(const type_list<Us...>&)
|
[[nodiscard]] consteval auto get_canonical_unit_impl(const type_list<Us...>&)
|
||||||
{
|
{
|
||||||
auto mag = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag);
|
auto m = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag);
|
||||||
auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit);
|
auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit);
|
||||||
return canonical_unit{mag, u};
|
return canonical_unit{m, u};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Unit T, typename... Expr>
|
template<Unit T, typename... Expr>
|
||||||
@ -402,12 +402,12 @@ using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
|
|||||||
* Multiplication by `1` returns the same unit, otherwise `scaled_unit` is being returned.
|
* Multiplication by `1` returns the same unit, otherwise `scaled_unit` is being returned.
|
||||||
*/
|
*/
|
||||||
template<Magnitude M, Unit U>
|
template<Magnitude M, Unit U>
|
||||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(M mag, const U u)
|
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(M, const U u)
|
||||||
{
|
{
|
||||||
if constexpr (mag == mp_units::mag<1>)
|
if constexpr (std::is_same_v<M, std::remove_cvref_t<decltype(mp_units::mag<1>)>>)
|
||||||
return u;
|
return u;
|
||||||
else
|
else
|
||||||
return scaled_unit<mag, U>{};
|
return scaled_unit<M{}, U>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval Unit auto operator*(Unit auto, Magnitude auto) = delete;
|
[[nodiscard]] consteval Unit auto operator*(Unit auto, Magnitude auto) = delete;
|
||||||
|
Reference in New Issue
Block a user