diff --git a/example/avg_velocity.cpp b/example/avg_velocity.cpp index 1b470eb3..49d65993 100644 --- a/example/avg_velocity.cpp +++ b/example/avg_velocity.cpp @@ -21,6 +21,7 @@ // SOFTWARE. #include +#include #include namespace { @@ -54,7 +55,7 @@ constexpr units::Velocity AUTO avg_speed(units::Length AUTO d, units::Time AUTO template void print_result(D distance, T duration, V velocity) { - const auto result_in_kmph = units::quantity_cast(velocity); + const auto result_in_kmph = units::quantity_cast>(velocity); std::cout << "Average speed of a car that makes " << distance << " in " << duration << " is " << result_in_kmph << ".\n"; } @@ -62,10 +63,10 @@ void print_result(D distance, T duration, V velocity) void example() { using namespace units; - using namespace units::si::literals; // SI (int) { + using namespace units::si::literals; constexpr Length AUTO distance = 220km; // constructed from a UDL constexpr si::time duration(2); // constructed from a value @@ -73,15 +74,13 @@ void example() print_result(distance, duration, fixed_int_si_avg_speed(distance, duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); - - // the framework will not allow a division (and multiplication) of different dimensions - // with two integral representation (at least one of them have to ba floating-point one) - print_result(distance, duration, si_avg_speed(quantity_cast(distance), duration)); - print_result(distance, duration, avg_speed(quantity_cast(distance), duration)); + print_result(distance, duration, si_avg_speed(distance, duration)); + print_result(distance, duration, avg_speed(distance, duration)); } // SI (double) { + using namespace units::si::literals; constexpr Length AUTO distance = 220.km; // constructed from a UDL constexpr si::time duration(2); // constructed from a value @@ -97,6 +96,7 @@ void example() // Customary Units (int) { + using namespace units::si::literals; constexpr Length AUTO distance = 140mi; // constructed from a UDL constexpr si::time duration(2); // constructed from a value @@ -106,15 +106,13 @@ void example() // (explicit cast needed) print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast(distance), duration)); print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); - - // the framework will not allow a division (and multiplication) of different dimensions - // with two integral representation (at least one of them have to ba floating-point one) - print_result(distance, duration, si_avg_speed(quantity_cast(distance), duration)); - print_result(distance, duration, avg_speed(quantity_cast(distance), duration)); + print_result(distance, duration, si_avg_speed(distance, duration)); + print_result(distance, duration, avg_speed(distance, duration)); } // Customary Units (double) { + using namespace units::si::literals; constexpr Length AUTO distance = 140.mi; // constructed from a UDL constexpr si::time duration(2); // constructed from a value @@ -129,6 +127,47 @@ void example() print_result(distance, duration, si_avg_speed(distance, duration)); print_result(distance, duration, avg_speed(distance, duration)); } + + // CGS (int) + { + using namespace units::cgs::literals; + constexpr Length AUTO distance = 22'000'000cm; // constructed from a UDL + constexpr cgs::time duration(2); // constructed from a value + + std::cout << "\nCGS units with 'int' as representation\n"; + + // it is not possible to make a lossless conversion of centimeters to meters on an integral type + // (explicit cast needed) + print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast(distance), duration)); + print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); + + // not possible to convert both a dimension and a unit with implicit cast + print_result(distance, duration, si_avg_speed(quantity_cast(distance), duration)); + + print_result(distance, duration, avg_speed(distance, duration)); + } + + // CGS (double) + { + using namespace units::cgs::literals; + constexpr Length AUTO distance = 22'000'000.cm; // constructed from a UDL + constexpr cgs::time duration(2); // constructed from a value + + std::cout << "\nCGS units with 'double' as representation\n"; + + // conversion from a floating-point to an integral type is a truncating one so an explicit cast is needed + // it is not possible to make a lossless conversion of centimeters to meters on an integral type + // (explicit cast needed) + print_result(distance, duration, fixed_int_si_avg_speed(quantity_cast>(distance), quantity_cast(duration))); + + print_result(distance, duration, fixed_double_si_avg_speed(distance, duration)); + + // not possible to convert both a dimension and a unit with implicit cast + print_result(distance, duration, si_avg_speed(quantity_cast(distance), duration)); + + print_result(distance, duration, avg_speed(distance, duration)); + } + } } // namespace diff --git a/src/include/units/bits/unit_op.h b/src/include/units/bits/unit_op.h deleted file mode 100644 index a4a1527a..00000000 --- a/src/include/units/bits/unit_op.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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 - -namespace units::detail { - -template::ratio>, - typename Ratio2 = ratio_divide::ratio>> -using unit_ratio_multiply = ratio_multiply; - -template::ratio>, - typename Ratio2 = ratio_divide::ratio>> -using unit_ratio_divide = ratio_divide; - -} // namespace units::detail diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 5f665e7f..c87e9175 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -24,7 +24,6 @@ #include #include -#include #include #if __GNUC__ >= 10 @@ -182,8 +181,7 @@ struct cast_ratio { * * This cast gets the target quantity type to cast to. For example: * - * using seconds = units::time; - * auto q1 = units::quantity_cast(1ms); + * auto q1 = units::quantity_cast>(1ms); * * @tparam To a target quantity type to cast to */ @@ -194,8 +192,8 @@ template { using c_ratio = detail::cast_ratio::type; using c_rep = std::common_type_t; - using ret_unit = downcast_unit; - using ret = quantity; + using ret_unit = downcast_unit; + using ret = quantity; using cast = detail::quantity_cast_impl; return cast::cast(q); } @@ -595,7 +593,7 @@ template template [[nodiscard]] constexpr Scalar AUTO operator*(const quantity& lhs, const quantity& rhs) - requires equivalent_dim> && detail::basic_arithmetic + requires detail::basic_arithmetic && equivalent_dim> { using common_rep = decltype(lhs.count() * rhs.count()); using ratio = ratio_multiply; @@ -604,13 +602,12 @@ template [[nodiscard]] constexpr Quantity AUTO operator*(const quantity& lhs, const quantity& rhs) - requires (!equivalent_dim>) && // TODO equivalent_derived_dim? - (treat_as_floating_point || - detail::unit_ratio_multiply::den == 1) && - detail::basic_arithmetic + requires detail::basic_arithmetic && (!equivalent_dim>) // TODO equivalent_derived_dim? { using dim = dimension_multiply; - using ratio = ratio_multiply, typename dimension_unit::ratio>; ; + using ratio1 = ratio_divide::ratio>; + using ratio2 = ratio_divide::ratio>; + using ratio = ratio_multiply, typename dimension_unit::ratio>; using unit = downcast_unit; using common_rep = decltype(lhs.count() * rhs.count()); using ret = quantity; @@ -655,15 +652,15 @@ template [[nodiscard]] constexpr Quantity AUTO operator/(const quantity& lhs, const quantity& rhs) - requires detail::basic_arithmetic && (!equivalent_dim) && // TODO equivalent_derived_dim? - (treat_as_floating_point || - detail::unit_ratio_divide::den == 1) + requires detail::basic_arithmetic && (!equivalent_dim) // TODO equivalent_derived_dim? { Expects(rhs.count() != 0); using common_rep = decltype(lhs.count() / rhs.count()); using dim = dimension_divide; - using ratio = ratio_multiply, typename dimension_unit::ratio>; + using ratio1 = ratio_divide::ratio>; + using ratio2 = ratio_divide::ratio>; + using ratio = ratio_multiply, typename dimension_unit::ratio>; using unit = downcast_unit; using ret = quantity; return ret(lhs.count() / rhs.count());