diff --git a/src/core/include/units/magnitude.h b/src/core/include/units/magnitude.h index 3a836b1b..eed32e16 100644 --- a/src/core/include/units/magnitude.h +++ b/src/core/include/units/magnitude.h @@ -336,14 +336,9 @@ struct magnitude { // The value of this magnitude, expressed in a given type. template - requires (std::is_floating_point_v || (detail::is_integral(BPs) && ...)) + requires (std::is_floating_point_v || (std::is_integral_v && is_magnitude_integral)) static constexpr T value = detail::checked_static_cast( (detail::compute_base_power(BPs) * ...)); - - // Trying to satisfy MSVC 14... - template - requires (std::is_floating_point_v || (detail::is_integral(BPs) && ...)) - constexpr T get_value() const { return magnitude::value; } }; // Implementation for Magnitude concept (below). @@ -360,6 +355,14 @@ static constexpr bool is_magnitude> = true; template concept Magnitude = detail::is_magnitude; +/** + * @brief Free-function access to the value of a Magnitude in a desired type. + * + * Can avoid the need for an unsightly `.template` keyword. + */ +template +T get_value(Magnitude auto m) { return m.template value; } + /** * @brief Convert any positive integer to a Magnitude. * diff --git a/test/unit_test/runtime/magnitude_test.cpp b/test/unit_test/runtime/magnitude_test.cpp index 20a370dd..42449f95 100644 --- a/test/unit_test/runtime/magnitude_test.cpp +++ b/test/unit_test/runtime/magnitude_test.cpp @@ -140,25 +140,25 @@ TEST_CASE("magnitude converts to numerical value") SECTION("Positive integer powers of integer bases give integer values") { constexpr auto mag_412 = as_magnitude<412>(); - check_same_type_and_value(mag_412.get_value(), 412); - check_same_type_and_value(mag_412.get_value(), std::size_t{412}); - check_same_type_and_value(mag_412.get_value(), 412.0f); - check_same_type_and_value(mag_412.get_value(), 412.0); + check_same_type_and_value(get_value(mag_412), 412); + check_same_type_and_value(get_value(mag_412), std::size_t{412}); + check_same_type_and_value(get_value(mag_412), 412.0f); + check_same_type_and_value(get_value(mag_412), 412.0); } SECTION("Negative integer powers of integer bases compute correct values") { constexpr auto mag_0p125 = as_magnitude(); - check_same_type_and_value(mag_0p125.get_value(), 0.125f); - check_same_type_and_value(mag_0p125.get_value(), 0.125); + check_same_type_and_value(get_value(mag_0p125), 0.125f); + check_same_type_and_value(get_value(mag_0p125), 0.125); } SECTION("pi to the 1 supplies correct values") { constexpr auto pi = pi_to_the<1>(); - check_same_type_and_value(pi.get_value(), std::numbers::pi_v); - check_same_type_and_value(pi.get_value(), std::numbers::pi_v); - check_same_type_and_value(pi.get_value(), std::numbers::pi_v); + check_same_type_and_value(get_value(pi), std::numbers::pi_v); + check_same_type_and_value(get_value(pi), std::numbers::pi_v); + check_same_type_and_value(get_value(pi), std::numbers::pi_v); } SECTION("pi to arbitrary power performs computations in most accurate type at compile time") @@ -170,7 +170,7 @@ TEST_CASE("magnitude converts to numerical value") constexpr auto via_float = cube(std::numbers::pi_v); constexpr auto via_long_double = static_cast(cube(std::numbers::pi_v)); - constexpr auto pi_cubed_value = pi_cubed.get_value(); + constexpr auto pi_cubed_value = pi_cubed.value; REQUIRE(pi_cubed_value != via_float); CHECK(pi_cubed_value == via_long_double); } @@ -181,22 +181,22 @@ TEST_CASE("magnitude converts to numerical value") // Naturally, we cannot actually write a test to verify a compiler error. But any of these can // be uncommented if desired to verify that it breaks the build. - // (void)as_magnitude<412>().get_value(); + // (void)as_magnitude<412>().value; // Would work for pow<62>: - // (void)pow<63>(as_magnitude<2>()).get_value(); + // (void)pow<63>(as_magnitude<2>()).value; // Would work for pow<63>: - // (void)pow<64>(as_magnitude<2>()).get_value(); + // (void)pow<64>(as_magnitude<2>()).value; - (void)pow<308>(as_magnitude<10>()).get_value(); // Compiles, correctly. - // (void)pow<309>(as_magnitude<10>()).get_value(); - // (void)pow<3099>(as_magnitude<10>()).get_value(); - // (void)pow<3099999>(as_magnitude<10>()).get_value(); + (void)pow<308>(as_magnitude<10>()).value; // Compiles, correctly. + // (void)pow<309>(as_magnitude<10>()).value; + // (void)pow<3099>(as_magnitude<10>()).value; + // (void)pow<3099999>(as_magnitude<10>()).value; auto sqrt_2 = pow(as_magnitude<2>()); CHECK(!is_integral(sqrt_2)); - // (void)sqrt_2.get_value(); + // (void)sqrt_2.value; } }