// 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. #include #include #include #include #ifdef MP_UNITS_IMPORT_STD import std; #else #include #include #endif namespace { /** * @brief Implicitly constructible and convertible representation type * * A wrapper type that is implicitly convertible from and to the contained type. * * @tparam T element type */ template class min_impl { T value_; public: using value_type = T; min_impl() = default; // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) min_impl(T v) noexcept : value_(v) {} template // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) min_impl(min_impl i) noexcept : value_(static_cast(static_cast(i))) { } // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr explicit(false) operator T() const noexcept { return value_; } }; } // namespace template struct std::common_type, min_impl> : std::type_identity>> {}; template struct std::common_type, U> : std::type_identity>> {}; template struct std::common_type> : std::type_identity>> {}; namespace { using namespace mp_units; static_assert(Representation>); static_assert(Representation>); // construction from a value is not allowed static_assert(!std::constructible_from>, min_impl>); static_assert(!std::convertible_to, quantity>>); static_assert(!std::constructible_from>, min_impl>); static_assert(!std::convertible_to, quantity>>); // multiply syntax should work template concept creates_quantity = Unit && requires { T{} * U; }; static_assert(creates_quantity, si::metre>); static_assert(creates_quantity, si::metre>); // multiply syntax static_assert(creates_quantity, one>); static_assert(creates_quantity, one>); static_assert(creates_quantity, percent>); static_assert(creates_quantity, percent>); // construction from a quantity // min_impl -> min_impl static_assert(std::constructible_from>, quantity>>); static_assert(std::convertible_to>, quantity>>); static_assert(std::constructible_from>, quantity>>); static_assert(std::convertible_to>, quantity>>); static_assert(std::constructible_from>, quantity>>); static_assert(std::convertible_to>, quantity>>); static_assert(!std::constructible_from>, quantity>>); // narrowing conversion static_assert(!std::convertible_to>, quantity>>); // T -> min_impl static_assert(std::constructible_from>, quantity>); static_assert(std::convertible_to, quantity>>); static_assert(std::constructible_from>, quantity>); static_assert(std::convertible_to, quantity>>); static_assert(std::constructible_from>, quantity>); static_assert(std::convertible_to, quantity>>); static_assert( !std::constructible_from>, quantity>); // narrowing conversion static_assert(!std::convertible_to, quantity>>); // min_impl -> T static_assert(std::constructible_from, quantity>>); static_assert(std::convertible_to>, quantity>); static_assert(std::constructible_from, quantity>>); static_assert(std::convertible_to>, quantity>); static_assert(std::constructible_from, quantity>>); static_assert(std::convertible_to>, quantity>); static_assert( !std::constructible_from, quantity>>); // narrowing conversion static_assert(!std::convertible_to>, quantity>); // arithmetic operators static_assert(min_impl{1} * si::metre + min_impl{1} * si::metre == min_impl{2} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::metre == min_impl{2.5} * si::metre); static_assert(1 * si::metre + min_impl{1} * si::metre == min_impl{2} * si::metre); static_assert(1 * si::metre + min_impl{1.5} * si::metre == min_impl{2.5} * si::metre); static_assert(min_impl{1} * si::metre + 1 * si::metre == min_impl{2} * si::metre); static_assert(min_impl{1} * si::metre + 1.5 * si::metre == min_impl{2.5} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::metre == 2 * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::metre == 2.5 * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1} * si::metre == min_impl{1'001} * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1.5} * si::metre == min_impl{1001.5} * si::metre); static_assert(1 * si::kilo + min_impl{1} * si::metre == min_impl{1'001} * si::metre); static_assert(1 * si::kilo + min_impl{1.5} * si::metre == min_impl{1001.5} * si::metre); static_assert(min_impl{1} * si::kilo + 1 * si::metre == min_impl{1'001} * si::metre); static_assert(min_impl{1} * si::kilo + 1.5 * si::metre == min_impl{1001.5} * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1} * si::metre == 1'001 * si::metre); static_assert(min_impl{1} * si::kilo + min_impl{1.5} * si::metre == 1001.5 * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::kilo == min_impl{1'001} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::kilo == min_impl{1'501} * si::metre); static_assert(1 * si::metre + min_impl{1} * si::kilo == min_impl{1'001} * si::metre); static_assert(1 * si::metre + min_impl{1.5} * si::kilo == min_impl{1'501} * si::metre); static_assert(min_impl{1} * si::metre + 1 * si::kilo == min_impl{1'001} * si::metre); static_assert(min_impl{1} * si::metre + 1.5 * si::kilo == min_impl{1'501} * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1} * si::kilo == 1'001 * si::metre); static_assert(min_impl{1} * si::metre + min_impl{1.5} * si::kilo == double{1'501} * si::metre); static_assert(min_impl{2} * si::metre - min_impl{1} * si::metre == min_impl{1} * si::metre); static_assert(min_impl{2} * si::metre - min_impl{1.5} * si::metre == min_impl{0.5} * si::metre); static_assert(2 * si::metre - min_impl{1} * si::metre == min_impl{1} * si::metre); static_assert(2 * si::metre - min_impl{1.5} * si::metre == min_impl{0.5} * si::metre); static_assert(min_impl{2} * si::metre - 1 * si::metre == min_impl{1} * si::metre); static_assert(min_impl{2} * si::metre - 1.5 * si::metre == min_impl{0.5} * si::metre); static_assert(min_impl{2} * si::metre - min_impl{1} * si::metre == 1 * si::metre); static_assert(min_impl{2} * si::metre - min_impl{1.5} * si::metre == 0.5 * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1} * si::metre == min_impl{1'999} * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1.5} * si::metre == min_impl{1998.5} * si::metre); static_assert(2 * si::kilo - min_impl{1} * si::metre == min_impl{1'999} * si::metre); static_assert(2 * si::kilo - min_impl{1.5} * si::metre == min_impl{1998.5} * si::metre); static_assert(min_impl{2} * si::kilo - 1 * si::metre == min_impl{1'999} * si::metre); static_assert(min_impl{2} * si::kilo - 1.5 * si::metre == min_impl{1998.5} * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1} * si::metre == 1'999 * si::metre); static_assert(min_impl{2} * si::kilo - min_impl{1.5} * si::metre == 1998.5 * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1} * si::kilo == min_impl{1'000} * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1.5} * si::kilo == min_impl{500} * si::metre); static_assert(2'000 * si::metre - min_impl{1} * si::kilo == min_impl{1'000} * si::metre); static_assert(2'000 * si::metre - min_impl{1.5} * si::kilo == min_impl{500} * si::metre); static_assert(min_impl{2'000} * si::metre - 1 * si::kilo == min_impl{1'000} * si::metre); static_assert(min_impl{2'000} * si::metre - 1.5 * si::kilo == min_impl{500} * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1} * si::kilo == 1'000 * si::metre); static_assert(min_impl{2'000} * si::metre - min_impl{1.5} * si::kilo == double{500} * si::metre); static_assert(min_impl{123} * si::metre * min_impl(1.5) == min_impl{184.5} * si::metre); static_assert(min_impl{123} * si::metre * 1.5 == min_impl{184.5} * si::metre); static_assert(123 * si::metre * min_impl(1.5) == min_impl{184.5} * si::metre); static_assert(min_impl{123} * si::metre * (min_impl(1.5) * one) == min_impl{184.5} * si::metre); static_assert(min_impl{123} * si::metre * (1.5 * one) == min_impl{184.5} * si::metre); static_assert(123 * si::metre * (min_impl(1.5) * one) == min_impl{184.5} * si::metre); static_assert(min_impl(1.5) * min_impl{123} * si::metre == min_impl{184.5} * si::metre); static_assert(min_impl(1.5) * 123 * si::metre == min_impl{184.5} * si::metre); static_assert(1.5 * min_impl{123} * si::metre == min_impl{184.5} * si::metre); static_assert(min_impl(1.5) * one * (min_impl{123} * si::metre) == min_impl{184.5} * si::metre); static_assert(min_impl(1.5) * one * (123 * si::metre) == min_impl{184.5} * si::metre); static_assert(1.5 * one * (min_impl{123} * si::metre) == min_impl{184.5} * si::metre); #ifndef MP_UNITS_COMP_CLANG static_assert(min_impl{123} * si::metre / min_impl(2.) == min_impl{61.5} * si::metre); static_assert(min_impl{123} * si::metre / 2. == min_impl{61.5} * si::metre); static_assert(123 * si::metre / min_impl(2.) == min_impl{61.5} * si::metre); static_assert(min_impl{123} * si::metre / (min_impl(2.) * one) == min_impl{61.5} * si::metre); static_assert(min_impl{123} * si::metre / (2. * one) == min_impl{61.5} * si::metre); static_assert(123 * si::metre / (min_impl(2.) * one) == min_impl{61.5} * si::metre); static_assert(min_impl{123} * si::metre / (min_impl{2.} * si::metre) == 61.5 * one); static_assert(min_impl{123} * si::metre / (2. * si::metre) == 61.5 * one); static_assert(123 * si::metre / (min_impl{2.} * si::metre) == 61.5 * one); #endif static_assert(min_impl{123} * si::metre % (min_impl(100) * si::metre) == 23 * si::metre); static_assert(min_impl{123} * si::metre % (100 * si::metre) == 23 * si::metre); static_assert(123 * si::metre % (min_impl(100) * si::metre) == 23 * si::metre); } // namespace