diff --git a/conanfile.py b/conanfile.py index 3a8fd5f5..5a876a11 100644 --- a/conanfile.py +++ b/conanfile.py @@ -94,7 +94,7 @@ class MPUnitsConan(ConanFile): "gcc": "12", "clang": "16", "apple-clang": "15", - "msvc": "", + "msvc": "194", }, }, "std_format": { diff --git a/example/measurement.cpp b/example/measurement.cpp index d61c8d2e..b0cf594b 100644 --- a/example/measurement.cpp +++ b/example/measurement.cpp @@ -151,7 +151,7 @@ void example() const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * m / s2); const auto time = measurement{1.2, 0.1} * s; - const MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(QuantityOf) auto velocity = acceleration * time; + const QuantityOf auto velocity = acceleration * time; std::cout << acceleration << " * " << time << " = " << velocity << " = " << velocity.in(km / h) << '\n'; const auto length = measurement{123., 1.} * m; diff --git a/src/core/include/mp-units/bits/fmt.h b/src/core/include/mp-units/bits/fmt.h index 9889b971..d55633a6 100644 --- a/src/core/include/mp-units/bits/fmt.h +++ b/src/core/include/mp-units/bits/fmt.h @@ -189,6 +189,8 @@ constexpr void handle_dynamic_spec(int& value, fmt_arg_ref [[nodiscard]] constexpr unsigned long long operator()(T value) const @@ -199,9 +201,9 @@ struct width_checker { return static_cast(value); } MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("width is not integer")); - return 0; } }; +MP_UNITS_DIAGNOSTIC_POP MP_UNITS_EXPORT_END @@ -253,7 +255,6 @@ template if (c == '%') return begin; // mp-units extension if (!::mp_units::detail::is_name_start(c)) { MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string")); - return begin; } auto it = begin; do { @@ -372,7 +373,6 @@ template if (c == '}') return begin; if (c == '{') { MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid fill character '{'")); - return begin; } specs.fill = {begin, to_unsigned(p - begin)}; begin = p + 1; diff --git a/src/core/include/mp-units/bits/get_associated_quantity.h b/src/core/include/mp-units/bits/get_associated_quantity.h index 881c61e8..d976b17e 100644 --- a/src/core/include/mp-units/bits/get_associated_quantity.h +++ b/src/core/include/mp-units/bits/get_associated_quantity.h @@ -76,9 +76,9 @@ template template [[nodiscard]] consteval auto get_associated_quantity(U u) { - constexpr bool all_kinds = all_are_kinds(u); + constexpr bool all_kinds = all_are_kinds(U{}); if constexpr (all_kinds) - return kind_of; + return kind_of; else return get_associated_quantity_impl(u); } diff --git a/src/core/include/mp-units/bits/hacks.h b/src/core/include/mp-units/bits/hacks.h index 6dbba51b..2481eb8c 100644 --- a/src/core/include/mp-units/bits/hacks.h +++ b/src/core/include/mp-units/bits/hacks.h @@ -80,16 +80,6 @@ // workarounds for https://cplusplus.github.io/CWG/issues/2387.html #define MP_UNITS_INLINE inline -#if MP_UNITS_COMP_MSVC - -#define MP_UNITS_TYPENAME typename - -#else - -#define MP_UNITS_TYPENAME - -#endif - #if MP_UNITS_COMP_GCC #define MP_UNITS_REMOVE_CONST(expr) std::remove_const_t @@ -125,13 +115,15 @@ inline constexpr from_range_t from_range{}; #if MP_UNITS_COMP_MSVC -#define MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(X) #define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X) +#define MP_UNITS_EXPRESSION_WORKAROUND(x) (x) +#define MP_UNITS_IS_VALUE_WORKAROUND(x) (x) #else -#define MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(X) X #define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X) X +#define MP_UNITS_EXPRESSION_WORKAROUND(x) x +#define MP_UNITS_IS_VALUE_WORKAROUND(x) x #endif diff --git a/src/core/include/mp-units/bits/sudo_cast.h b/src/core/include/mp-units/bits/sudo_cast.h index b8a9d7fd..137c9d30 100644 --- a/src/core/include/mp-units/bits/sudo_cast.h +++ b/src/core/include/mp-units/bits/sudo_cast.h @@ -30,9 +30,21 @@ namespace mp_units::detail { +template +struct has_common_type_impl : std::false_type {}; + +template +struct has_common_type_impl>, Ts...> : std::true_type {}; + +template +using has_common_type = typename has_common_type_impl::type; + +template +constexpr bool has_common_type_v = has_common_type_impl::value; + template -using maybe_common_type = std::conditional_t; }, - std::common_type, std::type_identity>::type; +using maybe_common_type = + std::conditional_t, std::common_type, std::type_identity>::type; /** * @brief Type-related details about the conversion from one quantity to another diff --git a/src/core/include/mp-units/bits/type_list.h b/src/core/include/mp-units/bits/type_list.h index 913a7a94..636c1df1 100644 --- a/src/core/include/mp-units/bits/type_list.h +++ b/src/core/include/mp-units/bits/type_list.h @@ -68,7 +68,7 @@ struct type_list_map_impl, To> { }; template typename To> -using type_list_map = MP_UNITS_TYPENAME type_list_map_impl::type; +using type_list_map = type_list_map_impl::type; // element @@ -105,7 +105,7 @@ struct type_list_front_impl> { }; template -using type_list_front = MP_UNITS_TYPENAME type_list_front_impl::type; +using type_list_front = type_list_front_impl::type; // back template @@ -121,7 +121,7 @@ struct type_list_push_front_impl, NewTypes...> { }; template -using type_list_push_front = MP_UNITS_TYPENAME type_list_push_front_impl::type; +using type_list_push_front = type_list_push_front_impl::type; // push_back template @@ -133,7 +133,7 @@ struct type_list_push_back_impl, NewTypes...> { }; template -using type_list_push_back = MP_UNITS_TYPENAME type_list_push_back_impl::type; +using type_list_push_back = type_list_push_back_impl::type; // join template @@ -143,11 +143,11 @@ struct type_list_join_impl { template typename List, typename... First, typename... Second, typename... Rest> struct type_list_join_impl, List, Rest...> { - using type = MP_UNITS_TYPENAME type_list_join_impl, Rest...>::type; + using type = type_list_join_impl, Rest...>::type; }; template -using type_list_join = MP_UNITS_TYPENAME type_list_join_impl::type; +using type_list_join = type_list_join_impl::type; // split template @@ -195,19 +195,19 @@ template typename List, typename Lhs1, typename... LhsRest template typename Pred> requires Pred::value struct type_list_merge_sorted_impl, List, Pred> { - using type = MP_UNITS_TYPENAME type_list_push_front_impl< + using type = type_list_push_front_impl< typename type_list_merge_sorted_impl, List, Pred>::type, Lhs1>::type; }; template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, template typename Pred> struct type_list_merge_sorted_impl, List, Pred> { - using type = MP_UNITS_TYPENAME type_list_push_front_impl< + using type = type_list_push_front_impl< typename type_list_merge_sorted_impl, List, Pred>::type, Rhs1>::type; }; template typename Pred> -using type_list_merge_sorted = MP_UNITS_TYPENAME type_list_merge_sorted_impl::type; +using type_list_merge_sorted = type_list_merge_sorted_impl::type; // sort template typename Pred> @@ -227,13 +227,13 @@ template typename List, typename... Types, template, Pred> { using types = List; using split = type_list_split_half>; - using sorted_left = MP_UNITS_TYPENAME type_list_sort_impl::type; - using sorted_right = MP_UNITS_TYPENAME type_list_sort_impl::type; - using type = MP_UNITS_TYPENAME type_list_merge_sorted_impl::type; + using sorted_left = type_list_sort_impl::type; + using sorted_right = type_list_sort_impl::type; + using type = type_list_merge_sorted_impl::type; }; template typename Pred> -using type_list_sort = MP_UNITS_TYPENAME type_list_sort_impl::type; +using type_list_sort = type_list_sort_impl::type; } // namespace mp_units::detail diff --git a/src/core/include/mp-units/ext/type_traits.h b/src/core/include/mp-units/ext/type_traits.h index 11b2b97b..2ee78e2a 100644 --- a/src/core/include/mp-units/ext/type_traits.h +++ b/src/core/include/mp-units/ext/type_traits.h @@ -56,7 +56,7 @@ struct conditional_impl { MP_UNITS_EXPORT_BEGIN template -using conditional = MP_UNITS_TYPENAME detail::conditional_impl::template type; +using conditional = detail::conditional_impl::template type; // is_same template @@ -98,7 +98,7 @@ namespace detail { template struct get_value_type { - using type = MP_UNITS_TYPENAME T::value_type; + using type = T::value_type; }; template @@ -111,13 +111,13 @@ struct get_element_type { template requires requires { typename T::value_type; } || requires { typename T::element_type; } struct wrapped_type { - using type = MP_UNITS_TYPENAME + using type = conditional, detail::get_element_type>::type; }; template requires requires { typename T::value_type; } || requires { typename T::element_type; } -using wrapped_type_t = MP_UNITS_TYPENAME wrapped_type::type; +using wrapped_type_t = wrapped_type::type; template struct value_type { @@ -127,11 +127,11 @@ struct value_type { template requires requires { typename wrapped_type_t; } struct value_type { - using type = MP_UNITS_TYPENAME wrapped_type_t; + using type = wrapped_type_t; }; template -using value_type_t = MP_UNITS_TYPENAME value_type::type; +using value_type_t = value_type::type; template concept one_of = (false || ... || std::same_as); diff --git a/src/core/include/mp-units/format.h b/src/core/include/mp-units/format.h index 8cc5f25e..6c76b5f8 100644 --- a/src/core/include/mp-units/format.h +++ b/src/core/include/mp-units/format.h @@ -47,8 +47,8 @@ namespace mp_units::detail { template [[nodiscard]] constexpr const Char* at_most_one_of(const Char* begin, const Char* end, std::string_view modifiers) { - const Char* const it = find_first_of(begin, end, modifiers.begin(), modifiers.end()); - if (it != end && find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end) + const Char* const it = mp_units::detail::find_first_of(begin, end, modifiers.begin(), modifiers.end()); + if (it != end && mp_units::detail::find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end) throw MP_UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) + "' unit modifiers may be used in the format spec"); return it; @@ -452,7 +452,7 @@ class MP_UNITS_STD_FMT::formatter, Char> { } // user provided format quantity_formatter f{*this, out, q, locale}; - parse_quantity_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f); + parse_quantity_specs(modifiers_format_str_.data(), modifiers_format_str_.data() + modifiers_format_str_.size(), f); return f.out; } diff --git a/src/core/include/mp-units/framework/construction_helpers.h b/src/core/include/mp-units/framework/construction_helpers.h index ac24dd57..43eade94 100644 --- a/src/core/include/mp-units/framework/construction_helpers.h +++ b/src/core/include/mp-units/framework/construction_helpers.h @@ -40,7 +40,7 @@ namespace mp_units { template struct delta_ { template Rep = std::remove_cvref_t> - [[nodiscard]] constexpr quantity operator()(FwdRep&& lhs) const + [[nodiscard]] constexpr quantity operator()(FwdRep&& lhs) const { return quantity{std::forward(lhs), R{}}; } @@ -49,7 +49,8 @@ struct delta_ { template struct absolute_ { template Rep = std::remove_cvref_t> - [[nodiscard]] constexpr quantity_point operator()(FwdRep&& lhs) const + [[nodiscard]] constexpr quantity_point + operator()(FwdRep&& lhs) const { return quantity_point{quantity{std::forward(lhs), R{}}}; } diff --git a/src/core/include/mp-units/framework/dimension_concepts.h b/src/core/include/mp-units/framework/dimension_concepts.h index 9bf7b3b1..5f726c2b 100644 --- a/src/core/include/mp-units/framework/dimension_concepts.h +++ b/src/core/include/mp-units/framework/dimension_concepts.h @@ -54,7 +54,7 @@ void to_base_specialization_of_base_dimension(const volatile base_dimension constexpr bool is_derived_from_specialization_of_base_dimension = - requires(T* t) { to_base_specialization_of_base_dimension(t); }; + requires(T* type) { to_base_specialization_of_base_dimension(type); }; /** * @brief A concept matching all named base dimensions in the library. diff --git a/src/core/include/mp-units/framework/expression_template.h b/src/core/include/mp-units/framework/expression_template.h index fe64b227..45d3d4b6 100644 --- a/src/core/include/mp-units/framework/expression_template.h +++ b/src/core/include/mp-units/framework/expression_template.h @@ -122,7 +122,7 @@ struct expr_type_impl> : std::type_identity {}; } // namespace detail template -using expr_type = MP_UNITS_TYPENAME detail::expr_type_impl::type; +using expr_type = detail::expr_type_impl::type; namespace detail { @@ -182,25 +182,24 @@ struct expr_consolidate_impl> { template requires(!is_specialization_of_power) struct expr_consolidate_impl> { - using type = MP_UNITS_TYPENAME expr_consolidate_impl, Rest...>>::type; + using type = expr_consolidate_impl, Rest...>>::type; }; // replaces the instance of a type and a power of it with one with incremented power template struct expr_consolidate_impl, Rest...>> { - using type = - MP_UNITS_TYPENAME expr_consolidate_impl::exponent + 1>, Rest...>>::type; + using type = expr_consolidate_impl::exponent + 1>, Rest...>>::type; }; // accumulates the powers of instances of the same type (removes the element in case the accumulation result is `0`) template struct expr_consolidate_impl, power, Rest...>> { static constexpr ratio r = power::exponent + power::exponent; - using type = MP_UNITS_TYPENAME expr_consolidate_impl, Rest...>>::type; + using type = expr_consolidate_impl, Rest...>>::type; }; template -using expr_consolidate = MP_UNITS_TYPENAME expr_consolidate_impl::type; +using expr_consolidate = expr_consolidate_impl::type; /** diff --git a/src/core/include/mp-units/framework/magnitude.h b/src/core/include/mp-units/framework/magnitude.h index afe91564..71cde3fc 100644 --- a/src/core/include/mp-units/framework/magnitude.h +++ b/src/core/include/mp-units/framework/magnitude.h @@ -707,7 +707,8 @@ template void to_base_specialization_of_magnitude(const volatile magnitude*); template -constexpr bool is_derived_from_specialization_of_magnitude = requires(T* t) { to_base_specialization_of_magnitude(t); }; +constexpr bool is_derived_from_specialization_of_magnitude = + requires(T* type) { to_base_specialization_of_magnitude(type); }; template requires is_derived_from_specialization_of_magnitude diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index af641474..18490e07 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -435,7 +435,9 @@ public: } friend constexpr decltype(auto) operator*=(FwdQ&& lhs, const Value& v) { - lhs.numerical_value_is_an_implementation_detail_ *= v; + // TODO use *= when compiiler bug is resolved: + // https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445 + lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ * v; return std::forward(lhs); } @@ -447,7 +449,10 @@ public: } friend constexpr decltype(auto) operator*=(FwdQ1&& lhs, const Q2& rhs) { - lhs.numerical_value_is_an_implementation_detail_ *= rhs.numerical_value_is_an_implementation_detail_; + // TODO use *= when compiiler bug is resolved: + // https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445 + lhs.numerical_value_is_an_implementation_detail_ = + lhs.numerical_value_is_an_implementation_detail_ * rhs.numerical_value_is_an_implementation_detail_; return std::forward(lhs); } @@ -460,7 +465,9 @@ public: friend constexpr decltype(auto) operator/=(FwdQ&& lhs, const Value& v) { MP_UNITS_EXPECTS_DEBUG(v != quantity_values::zero()); - lhs.numerical_value_is_an_implementation_detail_ /= v; + // TODO use /= when compiiler bug is resolved: + // https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445 + lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ / v; return std::forward(lhs); } @@ -473,7 +480,10 @@ public: friend constexpr decltype(auto) operator/=(FwdQ1&& lhs, const Q2& rhs) { MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero()); - lhs.numerical_value_is_an_implementation_detail_ /= rhs.numerical_value_is_an_implementation_detail_; + // TODO use /= when compiiler bug is resolved: + // https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445 + lhs.numerical_value_is_an_implementation_detail_ = + lhs.numerical_value_is_an_implementation_detail_ / rhs.numerical_value_is_an_implementation_detail_; return std::forward(lhs); } diff --git a/src/core/include/mp-units/framework/quantity_concepts.h b/src/core/include/mp-units/framework/quantity_concepts.h index 66b03efe..cfdb705a 100644 --- a/src/core/include/mp-units/framework/quantity_concepts.h +++ b/src/core/include/mp-units/framework/quantity_concepts.h @@ -40,7 +40,8 @@ template void to_base_specialization_of_quantity(const volatile quantity*); template -constexpr bool is_derived_from_specialization_of_quantity = requires(T* t) { to_base_specialization_of_quantity(t); }; +constexpr bool is_derived_from_specialization_of_quantity = + requires(T* type) { to_base_specialization_of_quantity(type); }; } // namespace detail diff --git a/src/core/include/mp-units/framework/quantity_point.h b/src/core/include/mp-units/framework/quantity_point.h index 5c11e943..074cd8fa 100644 --- a/src/core/include/mp-units/framework/quantity_point.h +++ b/src/core/include/mp-units/framework/quantity_point.h @@ -53,13 +53,15 @@ template struct point_origin_interface { template Q = std::remove_cvref_t> - [[nodiscard]] friend constexpr quantity_point operator+(PO, FwdQ&& q) + [[nodiscard]] friend constexpr quantity_point + operator+(PO, FwdQ&& q) { return quantity_point{std::forward(q), PO{}}; } template Q = std::remove_cvref_t> - [[nodiscard]] friend constexpr quantity_point operator+(FwdQ&& q, PO po) + [[nodiscard]] friend constexpr quantity_point + operator+(FwdQ&& q, PO po) { return po + std::forward(q); } @@ -261,10 +263,9 @@ public: quantity_point& operator=(quantity_point&&) = default; template NewPO> - [[nodiscard]] constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(QuantityPointOf) auto point_for( - NewPO new_origin) const + [[nodiscard]] constexpr QuantityPointOf<(NewPO{})> auto point_for(NewPO new_origin) const { - if constexpr (is_same_v) + if constexpr (is_same_v) return *this; else return ::mp_units::quantity_point{*this - new_origin, new_origin}; @@ -326,42 +327,42 @@ public: requires detail::QuantityConvertibleTo> [[nodiscard]] constexpr QuantityPointOf auto in(ToU) const { - return ::mp_units::quantity_point{quantity_ref_from(PO).in(ToU{}), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).in(ToU{}), point_origin}; } template ToRep> requires detail::QuantityConvertibleTo> [[nodiscard]] constexpr QuantityPointOf auto in() const { - return ::mp_units::quantity_point{quantity_ref_from(PO).template in(), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in(), point_origin}; } template ToRep, detail::UnitCompatibleWith ToU> requires detail::QuantityConvertibleTo> [[nodiscard]] constexpr QuantityPointOf auto in(ToU) const { - return ::mp_units::quantity_point{quantity_ref_from(PO).template in(ToU{}), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in(ToU{}), point_origin}; } template ToU> requires requires(quantity_type q) { value_cast(q); } [[nodiscard]] constexpr QuantityPointOf auto force_in(ToU) const { - return ::mp_units::quantity_point{quantity_ref_from(PO).force_in(ToU{}), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).force_in(ToU{}), point_origin}; } template ToRep> requires requires(quantity_type q) { value_cast(q); } [[nodiscard]] constexpr QuantityPointOf auto force_in() const { - return ::mp_units::quantity_point{quantity_ref_from(PO).template force_in(), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in(), point_origin}; } template ToRep, detail::UnitCompatibleWith ToU> requires requires(quantity_type q) { value_cast(q); } [[nodiscard]] constexpr QuantityPointOf auto force_in(ToU) const { - return ::mp_units::quantity_point{quantity_ref_from(PO).template force_in(ToU{}), PO}; + return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in(ToU{}), point_origin}; } // conversion operators diff --git a/src/core/include/mp-units/framework/quantity_point_concepts.h b/src/core/include/mp-units/framework/quantity_point_concepts.h index 8176f6a7..2269f7ec 100644 --- a/src/core/include/mp-units/framework/quantity_point_concepts.h +++ b/src/core/include/mp-units/framework/quantity_point_concepts.h @@ -45,7 +45,7 @@ void to_base_specialization_of_absolute_point_origin(const volatile absolute_poi template constexpr bool is_derived_from_specialization_of_absolute_point_origin = - requires(T* t) { to_base_specialization_of_absolute_point_origin(t); }; + requires(T* type) { to_base_specialization_of_absolute_point_origin(type); }; } // namespace detail @@ -67,7 +67,7 @@ void to_base_specialization_of_relative_point_origin(const volatile relative_poi template constexpr bool is_derived_from_specialization_of_relative_point_origin = - requires(T* t) { to_base_specialization_of_relative_point_origin(t); }; + requires(T* type) { to_base_specialization_of_relative_point_origin(type); }; struct point_origin_interface; @@ -100,7 +100,7 @@ void to_base_specialization_of_quantity_point(const volatile quantity_point constexpr bool is_derived_from_specialization_of_quantity_point = - requires(T* t) { to_base_specialization_of_quantity_point(t); }; + requires(T* type) { to_base_specialization_of_quantity_point(type); }; template requires is_derived_from_specialization_of_quantity_point diff --git a/src/core/include/mp-units/framework/quantity_spec.h b/src/core/include/mp-units/framework/quantity_spec.h index 9510d119..ef21e47e 100644 --- a/src/core/include/mp-units/framework/quantity_spec.h +++ b/src/core/include/mp-units/framework/quantity_spec.h @@ -667,11 +667,11 @@ template // dimension_one is always the last one // otherwise, sort by typename template -[[nodiscard]] consteval bool ingredients_dimension_less(D1 lhs, D2 rhs) +[[nodiscard]] consteval bool ingredients_dimension_less(D1, D2) { - if constexpr (lhs == rhs || lhs == dimension_one) + if constexpr (D1{} == D2{} || D1{} == dimension_one) return false; - else if constexpr (rhs == dimension_one) + else if constexpr (D2{} == dimension_one) return true; else return detail::type_name() < detail::type_name(); @@ -760,15 +760,15 @@ template template [[nodiscard]] consteval auto explode(Q, type_list, type_list) { - constexpr auto n = get_complexity(Num{}); - constexpr auto d = get_complexity(Den{}); - constexpr auto max_compl = n > d ? n : d; + constexpr auto num = get_complexity(Num{}); + constexpr auto den = get_complexity(Den{}); + constexpr auto max_compl = num > den ? num : den; - if constexpr (max_compl == Complexity || ((n >= d && !requires { explode_to_equation(Num{}); }) || - (n < d && !requires { explode_to_equation(Den{}); }))) + if constexpr (max_compl == Complexity || ((num >= den && !requires { explode_to_equation(Num{}); }) || + (num < den && !requires { explode_to_equation(Den{}); }))) return explode_result{(map_power(Num{}) * ... * map_power(Nums{})) / (map_power(Den{}) * ... * map_power(Dens{}))}; else { - if constexpr (n >= d) { + if constexpr (num >= den) { constexpr auto res = explode_to_equation(Num{}); return explode((res.equation * ... * map_power(Nums{})) / (map_power(Den{}) * ... * map_power(Dens{}))) @@ -797,8 +797,8 @@ template template [[nodiscard]] consteval auto explode(Q, type_list<>, type_list) { - constexpr auto d = get_complexity(Den{}); - if constexpr (d == Complexity || !requires { explode_to_equation(Den{}); }) + constexpr auto den = get_complexity(Den{}); + if constexpr (den == Complexity || !requires { explode_to_equation(Den{}); }) return explode_result{dimensionless / (map_power(Den{}) * ... * map_power(Dens{}))}; else { constexpr auto res = explode_to_equation(Den{}); @@ -816,8 +816,8 @@ template template [[nodiscard]] consteval auto explode(Q q) { - constexpr auto c = get_complexity(Q{}); - if constexpr (c > Complexity) + constexpr auto complexity = get_complexity(Q{}); + if constexpr (complexity > Complexity) return explode(q, type_list_sort{}, type_list_sort{}); else @@ -827,8 +827,8 @@ template template [[nodiscard]] consteval auto explode(Q q) { - constexpr auto c = get_complexity(Q{}); - if constexpr (c > Complexity && requires { Q::_equation_; }) { + constexpr auto complexity = get_complexity(Q{}); + if constexpr (complexity > Complexity && requires { Q::_equation_; }) { constexpr auto res = explode_to_equation(Q{}); return explode(res.equation).common_convertibility_with(res); } else @@ -1340,15 +1340,15 @@ template using enum specs_convertible_result; return res == no ? no : yes; }; - if constexpr ((NamedQuantitySpec && NamedQuantitySpec) || - get_complexity(from_kind) == get_complexity(to_kind)) + if constexpr ((NamedQuantitySpec && NamedQuantitySpec) || + get_complexity(From{}) == get_complexity(To{})) return convertible_impl(from_kind, to_kind); - else if constexpr (get_complexity(from_kind) > get_complexity(to_kind)) + else if constexpr (get_complexity(From{}) > get_complexity(To{})) return exploded_kind_result( - convertible_impl(get_kind_tree_root(explode(from_kind).quantity), to_kind)); + convertible_impl(get_kind_tree_root(explode(from_kind).quantity), to_kind)); else return exploded_kind_result( - convertible_impl(from_kind, get_kind_tree_root(explode(to_kind).quantity))); + convertible_impl(from_kind, get_kind_tree_root(explode(to_kind).quantity))); } template @@ -1365,9 +1365,9 @@ template return no; else if constexpr (get_complexity(From{}) != get_complexity(To{})) { if constexpr (get_complexity(From{}) > get_complexity(To{})) - return convertible_impl(explode(from).quantity, to); + return convertible_impl(explode(from).quantity, to); else { - auto res = explode(to); + auto res = explode(to); return min(res.result, convertible_impl(from, res.quantity)); } } @@ -1392,7 +1392,7 @@ template else if constexpr (DerivedQuantitySpec && DerivedQuantitySpec) return are_ingredients_convertible(from, to); else if constexpr (DerivedQuantitySpec) { - auto res = explode(from); + auto res = explode(from); if constexpr (NamedQuantitySpec) return convertible_impl(res.quantity, to); else if constexpr (requires { to._equation_; }) { @@ -1401,7 +1401,7 @@ template } else return are_ingredients_convertible(from, to); } else if constexpr (DerivedQuantitySpec) { - auto res = explode(to); + auto res = explode(to); if constexpr (NamedQuantitySpec) return min(res.result, convertible_impl(from, res.quantity)); else if constexpr (requires { from._equation_; }) @@ -1492,9 +1492,9 @@ template MP_UNITS_EXPORT_BEGIN template -[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q) +[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q) { - return kind_of; + return kind_of; } [[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q) { return q; } diff --git a/src/core/include/mp-units/framework/quantity_spec_concepts.h b/src/core/include/mp-units/framework/quantity_spec_concepts.h index 296e7e9d..d780558e 100644 --- a/src/core/include/mp-units/framework/quantity_spec_concepts.h +++ b/src/core/include/mp-units/framework/quantity_spec_concepts.h @@ -71,7 +71,7 @@ void to_base_specialization_of_quantity_spec(const volatile quantity_spec constexpr bool is_derived_from_specialization_of_quantity_spec = - requires(T* t) { to_base_specialization_of_quantity_spec(t); }; + requires(T* type) { to_base_specialization_of_quantity_spec(type); }; /** * @brief Concept matching all named quantity specification types diff --git a/src/core/include/mp-units/framework/reference.h b/src/core/include/mp-units/framework/reference.h index 72d148fa..ea19739d 100644 --- a/src/core/include/mp-units/framework/reference.h +++ b/src/core/include/mp-units/framework/reference.h @@ -87,37 +87,49 @@ struct reference { } template - [[nodiscard]] friend consteval detail::reference_t operator*(reference, reference) + [[nodiscard]] friend consteval detail::reference_t + operator*(reference, reference) { return {}; } template - [[nodiscard]] friend consteval detail::reference_t operator*(reference, U2) + [[nodiscard]] friend consteval detail::reference_t<(MP_UNITS_EXPRESSION_WORKAROUND(Q{} * get_quantity_spec(U2{}))), + MP_UNITS_EXPRESSION_WORKAROUND(U{} * U2{})> + operator*(reference, U2) { return {}; } template - [[nodiscard]] friend consteval detail::reference_t operator*(U1, reference) + [[nodiscard]] friend consteval detail::reference_t + operator*(U1, reference) { return {}; } template - [[nodiscard]] friend consteval detail::reference_t operator/(reference, reference) + [[nodiscard]] friend consteval detail::reference_t + operator/(reference, reference) { return {}; } template - [[nodiscard]] friend consteval detail::reference_t operator/(reference, U2) + [[nodiscard]] friend consteval detail::reference_t + operator/(reference, U2) { return {}; } template - [[nodiscard]] friend consteval detail::reference_t operator/(U1, reference) + [[nodiscard]] friend consteval detail::reference_t + operator/(U1, reference) { return {}; } @@ -281,9 +293,9 @@ template } -> Unit; } { - return detail::reference_t{}; + common_unit(get_unit(R1{}), get_unit(R2{}), get_unit(rest)...)>{}; } MP_UNITS_EXPORT_END diff --git a/src/core/include/mp-units/framework/symbol_text.h b/src/core/include/mp-units/framework/symbol_text.h index f0a75313..a08a6844 100644 --- a/src/core/include/mp-units/framework/symbol_text.h +++ b/src/core/include/mp-units/framework/symbol_text.h @@ -128,9 +128,10 @@ public: MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(a)); } - constexpr symbol_text(const fixed_u8string& u, const fixed_string& a) : unicode_(u), ascii_(a) + constexpr symbol_text(const fixed_u8string& unicode, const fixed_string& ascii) : + unicode_(unicode), ascii_(ascii) { - MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(a.data_)); + MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(ascii.data_)); } [[nodiscard]] constexpr const auto& unicode() const { return unicode_; } diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index bc4fd7e0..332586eb 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -220,7 +220,7 @@ struct propagate_point_origin { template struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin { using _base_type_ = scaled_unit_impl; // exposition only - static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M; + static constexpr Magnitude auto mag = M; static constexpr U reference_unit{}; }; @@ -520,9 +520,9 @@ template template [[nodiscard]] consteval auto get_canonical_unit_impl(const type_list&) { - auto m = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag); + auto magnitude = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag); auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit); - return canonical_unit{m, u}; + return canonical_unit{magnitude, u}; } template @@ -632,8 +632,8 @@ template [[nodiscard]] consteval Unit auto common_unit(Unit auto u) { return u; } template + requires(convertible(U1{}, U2{})) [[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2) - requires(convertible(u1, u2)) { if constexpr (is_same_v) return u1; @@ -654,8 +654,8 @@ template else if constexpr (is_integral(canonical_rhs.mag / canonical_lhs.mag)) return u1; else { - constexpr auto cm = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag); - return scaled_unit{}; + constexpr auto common_magnitude = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag); + return scaled_unit{}; } } } diff --git a/src/core/include/mp-units/ostream.h b/src/core/include/mp-units/ostream.h index e2464bd7..15b6127b 100644 --- a/src/core/include/mp-units/ostream.h +++ b/src/core/include/mp-units/ostream.h @@ -85,13 +85,16 @@ std::basic_ostream& to_stream(std::basic_ostream& return os; } +template +constexpr bool is_mp_units_stream = requires(OStream os, T v) { detail::to_stream_impl(os, v); }; + } // namespace detail MP_UNITS_EXPORT_BEGIN template std::basic_ostream& operator<<(std::basic_ostream& os, const T& v) - requires requires { detail::to_stream_impl(os, v); } + requires detail::is_mp_units_stream, T> { return detail::to_stream(os, v); } diff --git a/src/core/include/mp-units/random.h b/src/core/include/mp-units/random.h index a470c3b0..5da89966 100644 --- a/src/core/include/mp-units/random.h +++ b/src/core/include/mp-units/random.h @@ -61,7 +61,7 @@ std::vector bl_qty_to_rep(std::initializer_list& bl) template std::vector fw_bl_pwc(std::initializer_list& bl, UnaryOperation fw) { - using rep = MP_UNITS_TYPENAME Q::rep; + using rep = Q::rep; std::vector w_bl; w_bl.reserve(bl.size()); for (const Q& qty : bl) { @@ -93,8 +93,8 @@ MP_UNITS_EXPORT_BEGIN template requires std::integral struct uniform_int_distribution : public std::uniform_int_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::uniform_int_distribution; + using rep = Q::rep; + using base = std::uniform_int_distribution; uniform_int_distribution() : base() {} uniform_int_distribution(const Q& a, const Q& b) : @@ -118,8 +118,8 @@ struct uniform_int_distribution : public std::uniform_int_distribution requires std::floating_point struct uniform_real_distribution : public std::uniform_real_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::uniform_real_distribution; + using rep = Q::rep; + using base = std::uniform_real_distribution; uniform_real_distribution() : base() {} uniform_real_distribution(const Q& a, const Q& b) : @@ -143,8 +143,8 @@ struct uniform_real_distribution : public std::uniform_real_distribution requires std::integral struct binomial_distribution : public std::binomial_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::binomial_distribution; + using rep = Q::rep; + using base = std::binomial_distribution; binomial_distribution() : base() {} binomial_distribution(const Q& t, double p) : base(t.numerical_value_ref_in(Q::unit), p) {} @@ -164,8 +164,8 @@ struct binomial_distribution : public std::binomial_distribution requires std::integral struct negative_binomial_distribution : public std::negative_binomial_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::negative_binomial_distribution; + using rep = Q::rep; + using base = std::negative_binomial_distribution; negative_binomial_distribution() : base() {} negative_binomial_distribution(const Q& k, double p) : base(k.numerical_value_ref_in(Q::unit), p) {} @@ -185,8 +185,8 @@ struct negative_binomial_distribution : public std::negative_binomial_distributi template requires std::integral struct geometric_distribution : public std::geometric_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::geometric_distribution; + using rep = Q::rep; + using base = std::geometric_distribution; geometric_distribution() : base() {} explicit geometric_distribution(double p) : base(p) {} @@ -204,8 +204,8 @@ struct geometric_distribution : public std::geometric_distribution requires std::integral struct poisson_distribution : public std::poisson_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::poisson_distribution; + using rep = Q::rep; + using base = std::poisson_distribution; poisson_distribution() : base() {} explicit poisson_distribution(double p) : base(p) {} @@ -223,8 +223,8 @@ struct poisson_distribution : public std::poisson_distribution template requires std::floating_point struct exponential_distribution : public std::exponential_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::exponential_distribution; + using rep = Q::rep; + using base = std::exponential_distribution; exponential_distribution() : base() {} explicit exponential_distribution(const rep& lambda) : base(lambda) {} @@ -242,8 +242,8 @@ struct exponential_distribution : public std::exponential_distribution requires std::floating_point struct gamma_distribution : public std::gamma_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::gamma_distribution; + using rep = Q::rep; + using base = std::gamma_distribution; gamma_distribution() : base() {} gamma_distribution(const rep& alpha, const rep& beta) : base(alpha, beta) {} @@ -261,8 +261,8 @@ struct gamma_distribution : public std::gamma_distribution { template requires std::floating_point struct weibull_distribution : public std::weibull_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::weibull_distribution; + using rep = Q::rep; + using base = std::weibull_distribution; weibull_distribution() : base() {} weibull_distribution(const rep& a, const rep& b) : base(a, b) {} @@ -280,8 +280,8 @@ struct weibull_distribution : public std::weibull_distribution template requires std::floating_point struct extreme_value_distribution : public std::extreme_value_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::extreme_value_distribution; + using rep = Q::rep; + using base = std::extreme_value_distribution; extreme_value_distribution() : base() {} extreme_value_distribution(const Q& a, const rep& b) : base(a.numerical_value_ref_in(Q::unit), b) {} @@ -301,8 +301,8 @@ struct extreme_value_distribution : public std::extreme_value_distribution requires std::floating_point struct normal_distribution : public std::normal_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::normal_distribution; + using rep = Q::rep; + using base = std::normal_distribution; normal_distribution() : base() {} normal_distribution(const Q& mean, const Q& stddev) : @@ -326,8 +326,8 @@ struct normal_distribution : public std::normal_distribution { template requires std::floating_point struct lognormal_distribution : public std::lognormal_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::lognormal_distribution; + using rep = Q::rep; + using base = std::lognormal_distribution; lognormal_distribution() : base() {} lognormal_distribution(const Q& m, const Q& s) : @@ -351,8 +351,8 @@ struct lognormal_distribution : public std::lognormal_distribution requires std::floating_point struct chi_squared_distribution : public std::chi_squared_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::chi_squared_distribution; + using rep = Q::rep; + using base = std::chi_squared_distribution; chi_squared_distribution() : base() {} explicit chi_squared_distribution(const rep& n) : base(n) {} @@ -370,8 +370,8 @@ struct chi_squared_distribution : public std::chi_squared_distribution requires std::floating_point struct cauchy_distribution : public std::cauchy_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::cauchy_distribution; + using rep = Q::rep; + using base = std::cauchy_distribution; cauchy_distribution() : base() {} cauchy_distribution(const Q& a, const Q& b) : @@ -395,8 +395,8 @@ struct cauchy_distribution : public std::cauchy_distribution { template requires std::floating_point struct fisher_f_distribution : public std::fisher_f_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::fisher_f_distribution; + using rep = Q::rep; + using base = std::fisher_f_distribution; fisher_f_distribution() : base() {} fisher_f_distribution(const rep& m, const rep& n) : base(m, n) {} @@ -414,8 +414,8 @@ struct fisher_f_distribution : public std::fisher_f_distribution requires std::floating_point struct student_t_distribution : public std::student_t_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::student_t_distribution; + using rep = Q::rep; + using base = std::student_t_distribution; student_t_distribution() : base() {} explicit student_t_distribution(const rep& n) : base(n) {} @@ -433,8 +433,8 @@ struct student_t_distribution : public std::student_t_distribution requires std::integral struct discrete_distribution : public std::discrete_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::discrete_distribution; + using rep = Q::rep; + using base = std::discrete_distribution; discrete_distribution() : base() {} @@ -464,8 +464,8 @@ struct discrete_distribution : public std::discrete_distribution requires std::floating_point class piecewise_constant_distribution : public std::piecewise_constant_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::piecewise_constant_distribution; + using rep = Q::rep; + using base = std::piecewise_constant_distribution; template piecewise_constant_distribution(const std::vector& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w) @@ -523,8 +523,8 @@ public: template requires std::floating_point class piecewise_linear_distribution : public std::piecewise_linear_distribution { - using rep = MP_UNITS_TYPENAME Q::rep; - using base = MP_UNITS_TYPENAME std::piecewise_linear_distribution; + using rep = Q::rep; + using base = std::piecewise_linear_distribution; template piecewise_linear_distribution(const std::vector& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w) diff --git a/src/systems/include/mp-units/systems/si/chrono.h b/src/systems/include/mp-units/systems/si/chrono.h index abf15b51..0ded9689 100644 --- a/src/systems/include/mp-units/systems/si/chrono.h +++ b/src/systems/include/mp-units/systems/si/chrono.h @@ -127,18 +127,18 @@ namespace detail { } // namespace detail -template Q> +template Q> [[nodiscard]] constexpr auto to_chrono_duration(const Q& q) { return std::chrono::duration{q}; } -template QP> +template QP> requires is_specialization_of, chrono_point_origin_> [[nodiscard]] constexpr auto to_chrono_time_point(const QP& qp) { - using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock; - using rep = MP_UNITS_TYPENAME QP::rep; + using clock = decltype(QP::absolute_point_origin)::clock; + using rep = QP::rep; using ret_type = std::chrono::time_point>; diff --git a/src/systems/include/mp-units/systems/si/math.h b/src/systems/include/mp-units/systems/si/math.h index b3d9b483..80568e37 100644 --- a/src/systems/include/mp-units/systems/si/math.h +++ b/src/systems/include/mp-units/systems/si/math.h @@ -43,7 +43,7 @@ import std; MP_UNITS_EXPORT namespace mp_units::si { -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { sin(v); } || requires(Rep v) { std::sin(v); } [[nodiscard]] inline QuantityOf auto sin(const quantity& q) noexcept { @@ -57,7 +57,7 @@ template auto R, typename Rep> return quantity{sin(q.numerical_value_in(radian)), one}; } -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { cos(v); } || requires(Rep v) { std::cos(v); } [[nodiscard]] inline QuantityOf auto cos(const quantity& q) noexcept { @@ -71,7 +71,7 @@ template auto R, typename Rep> return quantity{cos(q.numerical_value_in(radian)), one}; } -template auto R, typename Rep> +template auto R, typename Rep> requires requires(Rep v) { tan(v); } || requires(Rep v) { std::tan(v); } [[nodiscard]] inline QuantityOf auto tan(const quantity& q) noexcept { @@ -87,7 +87,8 @@ template auto R, typename Rep> template auto R, typename Rep> requires requires(Rep v) { asin(v); } || requires(Rep v) { std::asin(v); } -[[nodiscard]] inline QuantityOf auto asin(const quantity& q) noexcept +[[nodiscard]] inline QuantityOf auto asin( + const quantity& q) noexcept { using std::asin; if constexpr (!treat_as_floating_point) { @@ -101,7 +102,8 @@ template auto R, typename Rep> template auto R, typename Rep> requires requires(Rep v) { acos(v); } || requires(Rep v) { std::acos(v); } -[[nodiscard]] inline QuantityOf auto acos(const quantity& q) noexcept +[[nodiscard]] inline QuantityOf auto acos( + const quantity& q) noexcept { using std::acos; if constexpr (!treat_as_floating_point) { @@ -115,7 +117,8 @@ template auto R, typename Rep> template auto R, typename Rep> requires requires(Rep v) { atan(v); } || requires(Rep v) { std::atan(v); } -[[nodiscard]] inline QuantityOf auto atan(const quantity& q) noexcept +[[nodiscard]] inline QuantityOf auto atan( + const quantity& q) noexcept { using std::atan; if constexpr (!treat_as_floating_point) { @@ -132,8 +135,8 @@ template common_reference(R1, R2); requires requires { atan2(v1, v2); } || requires { std::atan2(v1, v2); }; } -[[nodiscard]] inline QuantityOf auto atan2(const quantity& y, - const quantity& x) noexcept +[[nodiscard]] inline QuantityOf auto atan2( + const quantity& y, const quantity& x) noexcept { constexpr auto ref = common_reference(R1, R2); constexpr auto unit = get_unit(ref); diff --git a/test_package/test_package.cpp b/test_package/test_package.cpp index 72a27f88..e676162f 100644 --- a/test_package/test_package.cpp +++ b/test_package/test_package.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include #include #include #include @@ -28,7 +29,8 @@ using namespace mp_units; -constexpr QuantityOf auto avg_speed(QuantityOf auto d, QuantityOf auto t) +constexpr QuantityOf auto avg_speed(QuantityOf auto d, + QuantityOf auto t) { return d / t; }