diff --git a/src/core/include/mp-units/bits/reference_concepts.h b/src/core/include/mp-units/bits/reference_concepts.h index 57299f317..f963a42a5 100644 --- a/src/core/include/mp-units/bits/reference_concepts.h +++ b/src/core/include/mp-units/bits/reference_concepts.h @@ -27,7 +27,7 @@ namespace mp_units { -template +template struct reference; namespace detail { @@ -36,7 +36,7 @@ namespace detail { template struct is_specialization_of_reference : std::false_type {}; -template +template struct is_specialization_of_reference> : std::true_type {}; } // namespace detail @@ -51,18 +51,18 @@ concept Reference = AssociatedUnit || detail::is_specialization_of_reference< [[nodiscard]] consteval QuantitySpec auto get_quantity_spec(AssociatedUnit auto u); -template +template [[nodiscard]] consteval QuantitySpec auto get_quantity_spec(reference) { - return Q; + return Q{}; } [[nodiscard]] consteval Unit auto get_unit(AssociatedUnit auto u) { return u; } -template +template [[nodiscard]] consteval Unit auto get_unit(reference) { - return U; + return U{}; } /** diff --git a/src/core/include/mp-units/quantity_spec.h b/src/core/include/mp-units/quantity_spec.h index 15e875472..f5e01bc8c 100644 --- a/src/core/include/mp-units/quantity_spec.h +++ b/src/core/include/mp-units/quantity_spec.h @@ -47,7 +47,7 @@ template if constexpr (detail::QuantityKindSpec) return u; else - return reference{}; + return reference{}; } // TODO revise the note in the below comment @@ -121,7 +121,7 @@ struct quantity_spec_interface { (explicitly_convertible(std::remove_reference_t::quantity_spec, self)) { return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, - reference::unit>{}}; + detail::make_reference(self, std::remove_cvref_t::unit)}; } #else template U> @@ -136,7 +136,7 @@ struct quantity_spec_interface { [[nodiscard]] constexpr Quantity auto operator()(Q&& q) const { return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, - reference::unit>{}}; + detail::make_reference(Self{}, std::remove_cvref_t::unit)}; } #endif }; @@ -313,7 +313,7 @@ struct quantity_spec : std::remove_const_t { [[nodiscard]] constexpr Quantity auto operator()(Q&& q) const { return quantity{std::forward(q).numerical_value_is_an_implementation_detail_, - reference::unit> {}}; + detail::make_reference(Self{}, std::remove_cvref_t::unit)}; } #endif }; diff --git a/src/core/include/mp-units/reference.h b/src/core/include/mp-units/reference.h index 607d21b1b..589d9bb6f 100644 --- a/src/core/include/mp-units/reference.h +++ b/src/core/include/mp-units/reference.h @@ -30,6 +30,13 @@ namespace mp_units { +namespace detail { + +template +using reference_t = reference, std::remove_const_t>; + +} + [[nodiscard]] consteval QuantitySpec auto get_quantity_spec(AssociatedUnit auto u) { return detail::get_associated_quantity(u); @@ -53,73 +60,57 @@ namespace mp_units { * The following syntaxes are not allowed: * `2 / kmph`, `kmph * 3`, `kmph / 4`, `70 * isq::length[km] / isq:time[h]`. */ -template +template struct reference { - template + template [[nodiscard]] friend consteval bool operator==(reference, reference) { - return Q == Q2 && U == U2; + return Q{} == Q2{} && U{} == U2{}; } template [[nodiscard]] friend consteval bool operator==(reference, U2 u2) { - return Q == get_quantity_spec(u2) && U == u2; + return Q{} == get_quantity_spec(u2) && U{} == u2; } - template - [[nodiscard]] friend consteval reference operator*(reference, reference) + template + [[nodiscard]] friend consteval detail::reference_t operator*(reference, reference) { return {}; } template -#if MP_UNITS_COMP_MSVC - [[nodiscard]] friend consteval decltype(reference{}) operator*(reference, U2) -#else - [[nodiscard]] friend consteval reference operator*(reference, U2) -#endif + [[nodiscard]] friend consteval detail::reference_t operator*(reference, U2) { return {}; } template -#if MP_UNITS_COMP_MSVC - [[nodiscard]] friend consteval decltype(reference{}) operator*(U1, reference) -#else - [[nodiscard]] friend consteval reference operator*(U1, reference) -#endif + [[nodiscard]] friend consteval detail::reference_t operator*(U1, reference) { return {}; } - template - [[nodiscard]] friend consteval reference operator/(reference, reference) + template + [[nodiscard]] friend consteval detail::reference_t operator/(reference, reference) { return {}; } template -#if MP_UNITS_COMP_MSVC - [[nodiscard]] friend consteval decltype(reference{}) operator/(reference, U2) -#else - [[nodiscard]] friend consteval reference operator/(reference, U2) -#endif + [[nodiscard]] friend consteval detail::reference_t operator/(reference, U2) { return {}; } template -#if MP_UNITS_COMP_MSVC - [[nodiscard]] friend consteval decltype(reference{}) operator/(U1, reference) -#else - [[nodiscard]] friend consteval reference operator/(U1, reference) -#endif + [[nodiscard]] friend consteval detail::reference_t operator/(U1, reference) { return {}; } - [[nodiscard]] friend consteval reference inverse(reference) { return {}; } + [[nodiscard]] friend consteval detail::reference_t inverse(reference) { return {}; } /** * @brief Computes the value of a reference raised to the `Num/Den` power @@ -132,7 +123,7 @@ struct reference { */ template requires detail::non_zero - [[nodiscard]] friend consteval reference(Q), pow(U)> pow(reference) + [[nodiscard]] friend consteval detail::reference_t(Q{}), pow(U{})> pow(reference) { return {}; } @@ -144,7 +135,7 @@ struct reference { * * @return The result of computation */ - [[nodiscard]] friend consteval reference sqrt(reference) { return {}; } + [[nodiscard]] friend consteval detail::reference_t sqrt(reference) { return {}; } /** * @brief Computes the cubic root of a reference @@ -153,24 +144,24 @@ struct reference { * * @return The result of computation */ - [[nodiscard]] friend consteval reference cbrt(reference) { return {}; } + [[nodiscard]] friend consteval detail::reference_t cbrt(reference) { return {}; } - template + template [[nodiscard]] friend consteval bool convertible(reference, reference) { - return implicitly_convertible(Q, Q2) && convertible(U, U2); + return implicitly_convertible(Q{}, Q2{}) && convertible(U{}, U2{}); } template [[nodiscard]] friend consteval bool convertible(reference, U2 u2) { - return implicitly_convertible(Q, get_quantity_spec(u2)) && convertible(U, u2); + return implicitly_convertible(Q{}, get_quantity_spec(u2)) && convertible(U{}, u2); } template [[nodiscard]] friend consteval bool convertible(U1 u1, reference) { - return implicitly_convertible(get_quantity_spec(u1), Q) && convertible(u1, U); + return implicitly_convertible(get_quantity_spec(u1), Q{}) && convertible(u1, U{}); } }; @@ -246,8 +237,9 @@ template } -> Unit; } { - return reference{}; + return detail::reference_t{}; } namespace detail { @@ -258,8 +250,8 @@ template return {}; } -template -[[nodiscard]] consteval reference clone_reference_with(reference) +template +[[nodiscard]] consteval reference> clone_reference_with(reference) { return {}; } diff --git a/src/core/include/mp-units/system_reference.h b/src/core/include/mp-units/system_reference.h index 59f4769c0..fed03ae31 100644 --- a/src/core/include/mp-units/system_reference.h +++ b/src/core/include/mp-units/system_reference.h @@ -65,9 +65,9 @@ struct system_reference { template requires(convertible(coherent_unit, U{})) #if MP_UNITS_COMP_MSVC - [[nodiscard]] constexpr decltype(reference{}) operator[](U) const + [[nodiscard]] constexpr decltype(reference, U>{}) operator[](U) const #else - [[nodiscard]] constexpr reference operator[](U) const + [[nodiscard]] constexpr reference, U> operator[](U) const #endif { return {}; diff --git a/test/static/reference_test.cpp b/test/static/reference_test.cpp index 8da7fa48b..fc7bb17e8 100644 --- a/test/static/reference_test.cpp +++ b/test/static/reference_test.cpp @@ -101,10 +101,12 @@ inline constexpr struct bit_ : named_unit<"bit", one, kind_of> // clang-format on -static_assert(is_of_type>); +static_assert(is_of_type>); static_assert(is_of_type[metre], metre_>); -static_assert(is_of_type<(length / time)[metre / second], reference>); +static_assert( + is_of_type<(length / time)[metre / second], + reference, std::remove_const_t>>); static_assert(is_of_type<(kind_of / kind_of