// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include #include #include #include namespace mp_units { [[nodiscard]] consteval QuantitySpec auto get_quantity_spec(AssociatedUnit auto u) { return detail::get_associated_quantity(u); } template [[nodiscard]] consteval QuantitySpec auto get_quantity_spec(reference) { return Q; } [[nodiscard]] consteval Unit auto get_unit(AssociatedUnit auto u) { return u; } template [[nodiscard]] consteval Unit auto get_unit(reference) { return U; } template Rep> class quantity; /** * @brief Quantity reference type * * Quantity reference describes all the properties of a quantity besides its * representation type. * * In most cases this class template is not explicitly instantiated by the user. * It is implicitly instantiated by the library's framework while binding a quantity * specification with a compatible unit. * * @code{.cpp} * Reference auto kmph = isq::speed[km / h]; * QuantityOf auto speed = 90 * kmph; * @endcode * * The following syntaxes are not allowed: * `2 / kmph`, `kmph * 3`, `kmph / 4`, `70 * isq::length[km] / isq:time[h]`. */ template struct reference { template [[nodiscard]] friend consteval bool operator==(reference, reference) { return Q == Q2 && U == U2; } template [[nodiscard]] friend consteval bool operator==(reference, U2 u2) { return Q == get_quantity_spec(u2) && U == u2; } template [[nodiscard]] friend consteval reference operator*(reference, reference) { return {}; } template [[nodiscard]] friend consteval reference operator*(reference, U2) { return {}; } template [[nodiscard]] friend consteval reference operator*(U1, reference) { return {}; } template [[nodiscard]] friend consteval reference operator/(reference, reference) { return {}; } template [[nodiscard]] friend consteval reference operator/(reference, U2) { return {}; } template [[nodiscard]] friend consteval reference operator/(U1, reference) { return {}; } template [[nodiscard]] friend consteval bool convertible_to(reference, reference) { return implicitly_convertible(Q, Q2) && convertible_to(U, U2); } template [[nodiscard]] friend consteval bool convertible_to(reference, U2 u2) { return implicitly_convertible(Q, get_quantity_spec(u2)) && convertible_to(U, u2); } template [[nodiscard]] friend consteval bool convertible_to(U1 u1, reference) { return implicitly_convertible(get_quantity_spec(u1), Q) && convertible_to(u1, U); } }; template requires RepresentationOf, get_quantity_spec(R{}).character> [[nodiscard]] constexpr quantity> operator*(Rep&& lhs, R) { return quantity>(std::forward(lhs)); } void /*Use `q * (1 * r)` rather than `q * r`.*/ operator*(Quantity auto, Reference auto) = delete; [[nodiscard]] consteval auto common_reference(AssociatedUnit auto u1, AssociatedUnit auto u2, AssociatedUnit auto... rest) requires requires { { common_unit(u1, u2, rest...) } -> AssociatedUnit; } { return common_unit(u1, u2, rest...); } template [[nodiscard]] consteval auto common_reference(R1 r1, R2 r2, Rest... rest) requires(!(AssociatedUnit && AssociatedUnit && (... && AssociatedUnit))) && requires { { common_quantity_spec(get_quantity_spec(r1), get_quantity_spec(r2), get_quantity_spec(rest)...) } -> QuantitySpec; { common_unit(get_unit(r1), get_unit(r2), get_unit(rest)...) } -> Unit; } { return reference{}; } } // namespace mp_units