// 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 "units/math.h" #include "units/physical/si/base/length.h" #include #include #include 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; constexpr min_impl(T v) noexcept : value_(v) {} template constexpr min_impl(min_impl i) noexcept : value_(static_cast(i.value_)) {} constexpr operator T() const noexcept { return value_; } }; } template struct std::common_type, min_impl> : std::common_type {}; template struct std::common_type, U> : std::common_type {}; template struct std::common_type> : std::common_type {}; namespace { using namespace units; using namespace units::physical::si; static_assert(QuantityValue>); static_assert(QuantityValue>); // construction from a value static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, length>>); static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, length>>); static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, length>>); static_assert(!std::constructible_from>, min_impl>); // narrowing conversion static_assert(!std::convertible_to, length>>); // construction from an underlying type static_assert(std::constructible_from>, int>); static_assert(!std::convertible_to>>); static_assert(std::constructible_from>, double>); static_assert(!std::convertible_to>>); static_assert(std::constructible_from>, int>); static_assert(!std::convertible_to>>); static_assert(!std::constructible_from>, double>); // narrowing conversion static_assert(!std::convertible_to>>); // dimensionless quantity is convertible from a value static_assert(std::constructible_from>, min_impl>); static_assert(std::convertible_to, dimensionless>>); static_assert(std::constructible_from>, min_impl>); static_assert(std::convertible_to, dimensionless>>); static_assert(std::constructible_from>, min_impl>); static_assert(std::convertible_to, dimensionless>>); static_assert(!std::constructible_from>, min_impl>); // narrowing conversion static_assert(!std::convertible_to, dimensionless>>); // and underlying type static_assert(std::constructible_from>, int>); static_assert(std::convertible_to>>); static_assert(std::constructible_from>, double>); static_assert(std::convertible_to>>); static_assert(std::constructible_from>, int>); static_assert(std::convertible_to>>); static_assert(!std::constructible_from>, double>); // narrowing conversion static_assert(!std::convertible_to>>); // but only for ratio(1), otherwise not convertible static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, dimensionless>>); static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, dimensionless>>); static_assert(std::constructible_from>, min_impl>); static_assert(!std::convertible_to, dimensionless>>); static_assert(!std::constructible_from>, min_impl>); // narrowing conversion static_assert(!std::convertible_to, dimensionless>>); // implicit conversion tests static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(!std::constructible_from, min_impl>); // narrowing conversion static_assert(!std::convertible_to, length>); // construction from an underlying type static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, length>); static_assert(!std::constructible_from, min_impl>); // narrowing conversion static_assert(!std::convertible_to, length>); // dimensionless quantity is convertible from a value static_assert(std::constructible_from, min_impl>); static_assert(std::convertible_to, dimensionless>); static_assert(std::constructible_from, min_impl>); static_assert(std::convertible_to, dimensionless>); static_assert(std::constructible_from, min_impl>); static_assert(std::convertible_to, dimensionless>); static_assert(!std::constructible_from, min_impl>); // narrowing conversion static_assert(!std::convertible_to, dimensionless>); // but only for ratio(1), otherwise not convertible static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, dimensionless>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, dimensionless>); static_assert(std::constructible_from, min_impl>); static_assert(!std::convertible_to, dimensionless>); static_assert(!std::constructible_from, min_impl>); // narrowing conversion static_assert(!std::convertible_to, dimensionless>); // construction from a quantity // min_impl -> min_impl static_assert(std::constructible_from>, length>>); static_assert(std::convertible_to>, length>>); static_assert(std::constructible_from>, length>>); static_assert(std::convertible_to>, length>>); static_assert(std::constructible_from>, length>>); static_assert(std::convertible_to>, length>>); static_assert(!std::constructible_from>, length>>); // narrowing conversion static_assert(!std::convertible_to>, length>>); // T -> min_impl static_assert(std::constructible_from>, length>); static_assert(std::convertible_to, length>>); static_assert(std::constructible_from>, length>); static_assert(std::convertible_to, length>>); static_assert(std::constructible_from>, length>); static_assert(std::convertible_to, length>>); static_assert(!std::constructible_from>, length>); // narrowing conversion static_assert(!std::convertible_to, length>>); // min_impl -> T static_assert(std::constructible_from, length>>); static_assert(std::convertible_to>, length>); static_assert(std::constructible_from, length>>); static_assert(std::convertible_to>, length>); static_assert(std::constructible_from, length>>); static_assert(std::convertible_to>, length>); static_assert(!std::constructible_from, length>>); // narrowing conversion static_assert(!std::convertible_to>, length>); // arithmetic operators static_assert(length>(1) + length>(1) == length>(2)); static_assert(length>(1) + length>(1.5) == length>(2.5)); static_assert(length(1) + length>(1) == length>(2)); static_assert(length(1) + length>(1.5) == length>(2.5)); static_assert(length>(1) + length(1) == length>(2)); static_assert(length>(1) + length(1.5) == length>(2.5)); static_assert(length>(1) + length>(1) == length(2)); static_assert(length>(1) + length>(1.5) == length(2.5)); static_assert(length>(1) + length>(1) == length>(1001)); static_assert(length>(1) + length>(1.5) == length>(1001.5)); static_assert(length(1) + length>(1) == length>(1001)); static_assert(length(1) + length>(1.5) == length>(1001.5)); static_assert(length>(1) + length(1) == length>(1001)); static_assert(length>(1) + length(1.5) == length>(1001.5)); static_assert(length>(1) + length>(1) == length(1001)); static_assert(length>(1) + length>(1.5) == length(1001.5)); static_assert(length>(1) + length>(1) == length>(1001)); static_assert(length>(1) + length>(1.5) == length>(1501)); static_assert(length(1) + length>(1) == length>(1001)); static_assert(length(1) + length>(1.5) == length>(1501)); static_assert(length>(1) + length(1) == length>(1001)); static_assert(length>(1) + length(1.5) == length>(1501)); static_assert(length>(1) + length>(1) == length(1001)); static_assert(length>(1) + length>(1.5) == length(1501)); static_assert(length>(2) - length>(1) == length>(1)); static_assert(length>(2) - length>(1.5) == length>(0.5)); static_assert(length(2) - length>(1) == length>(1)); static_assert(length(2) - length>(1.5) == length>(0.5)); static_assert(length>(2) - length(1) == length>(1)); static_assert(length>(2) - length(1.5) == length>(0.5)); static_assert(length>(2) - length>(1) == length(1)); static_assert(length>(2) - length>(1.5) == length(0.5)); static_assert(length>(2) - length>(1) == length>(1999)); static_assert(length>(2) - length>(1.5) == length>(1998.5)); static_assert(length(2) - length>(1) == length>(1999)); static_assert(length(2) - length>(1.5) == length>(1998.5)); static_assert(length>(2) - length(1) == length>(1999)); static_assert(length>(2) - length(1.5) == length>(1998.5)); static_assert(length>(2) - length>(1) == length(1999)); static_assert(length>(2) - length>(1.5) == length(1998.5)); static_assert(length>(2000) - length>(1) == length>(1000)); static_assert(length>(2000) - length>(1.5) == length>(500)); static_assert(length(2000) - length>(1) == length>(1000)); static_assert(length(2000) - length>(1.5) == length>(500)); static_assert(length>(2000) - length(1) == length>(1000)); static_assert(length>(2000) - length(1.5) == length>(500)); static_assert(length>(2000) - length>(1) == length(1000)); static_assert(length>(2000) - length>(1.5) == length(500)); static_assert(length>(123) * min_impl(1.5) == length>(184.5)); static_assert(length>(123) * 1.5 == length>(184.5)); static_assert(length(123) * min_impl(1.5) == length>(184.5)); static_assert(length>(123) * quantity{min_impl(1.5)} == length>(184.5)); static_assert(length>(123) * quantity{1.5} == length>(184.5)); static_assert(length(123) * quantity{min_impl(1.5)} == length>(184.5)); static_assert(min_impl(1.5) * length>(123) == length>(184.5)); static_assert(min_impl(1.5) * length(123) == length>(184.5)); static_assert(1.5 * length>(123) == length>(184.5)); static_assert(quantity{min_impl(1.5)} * length>(123) == length>(184.5)); static_assert(quantity{min_impl(1.5)} * length(123) == length>(184.5)); static_assert(quantity{1.5} * length>(123) == length>(184.5)); static_assert(length>(123) / min_impl(2.) == length>(61.5)); static_assert(length>(123) / 2. == length>(61.5)); static_assert(length(123) / min_impl(2.) == length>(61.5)); static_assert(length>(123) / quantity{min_impl(2.)} == length>(61.5)); static_assert(length>(123) / quantity{2.} == length>(61.5)); static_assert(length(123) / quantity{min_impl(2.)} == length>(61.5)); static_assert(length>(123) / length>(2.) == 61.5); static_assert(length>(123) / length(2.) == 61.5); static_assert(length(123) / length>(2.) == 61.5); static_assert(length>(123) % min_impl(100) == length(23)); static_assert(length>(123) % 100 == length(23)); static_assert(length(123) % min_impl(100) == length(23)); static_assert(length>(123) % quantity{min_impl(100)} == length(23)); static_assert(length>(123) % quantity{100} == length(23)); static_assert(length(123) % quantity{min_impl(100)} == length(23)); } // namespace