From bb2bf96d8031b2f4e06766a8866a32e8771d4b34 Mon Sep 17 00:00:00 2001 From: Ethan Slattery Date: Sun, 28 Apr 2024 15:07:01 -0700 Subject: [PATCH] remove fallback for floating point std::to_char If the compiler doesn't support std::to_char forfloating point, then the compile time option should disable use of std::to_char for all conversions. This avoids mixing and matching implementations. Either append_constexpr is used for all conversion, or std::to_char is used for all conversions. This slightly complicates the testing as there is now a two variable truth table as to the expected results when formatting -0.0. --- include/snitch/snitch_config.hpp.config | 7 +++++++ src/snitch_append.cpp | 19 ++++--------------- tests/runtime_tests/string_utility.cpp | 20 ++++++++++++++++---- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/include/snitch/snitch_config.hpp.config b/include/snitch/snitch_config.hpp.config index 69ffd63..d59977d 100644 --- a/include/snitch/snitch_config.hpp.config +++ b/include/snitch/snitch_config.hpp.config @@ -114,6 +114,13 @@ # define SNITCH_CONSTEXPR_FLOAT_USE_BITCAST 0 #endif +#if (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE <= 11) || \ + (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 14000) || \ + (defined(_MSC_VER) && _MSC_VER <= 1924) +# undef SNITCH_APPEND_TO_CHARS +# define SNITCH_APPEND_TO_CHARS 0 +#endif + #if SNITCH_SHARED_LIBRARY # if defined(_MSC_VER) # if defined(SNITCH_EXPORTS) diff --git a/src/snitch_append.cpp b/src/snitch_append.cpp index 4609371..cbff1de 100644 --- a/src/snitch_append.cpp +++ b/src/snitch_append.cpp @@ -3,10 +3,12 @@ #include "snitch/snitch_concepts.hpp" #include "snitch/snitch_string.hpp" -#include // for std::to_chars #include // for std::uintptr_t #include // for std::memmove -#include // for std::errc +#if SNITCH_APPEND_TO_CHARS +# include // for std::to_chars +# include // for std::errc +#endif namespace snitch::impl { namespace { @@ -14,13 +16,6 @@ using snitch::small_string_span; using namespace std::literals; #if SNITCH_APPEND_TO_CHARS -// libstdc++ version 11 or greater -// libc++ version 14 or greater -// MSVC 19.24 or greater (also known as Visual Studio 2019 16.4) -// Apple clang and others have no support as of April-2024 -# if (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE > 11) || \ - (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 14000) || \ - (defined(_MSC_VER) && _MSC_VER > 1924) template bool append_to(small_string_span ss, T value) noexcept { constexpr auto fmt = std::chars_format::scientific; @@ -43,12 +38,6 @@ bool append_to(small_string_span ss, T value) noexcept { ss.grow(end - ss.end()); return true; } -# else -template -bool append_to(small_string_span ss, T value) noexcept { - return append_constexpr(ss, value); -} -# endif template bool append_to(small_string_span ss, T value) noexcept { diff --git a/tests/runtime_tests/string_utility.cpp b/tests/runtime_tests/string_utility.cpp index fcf6a38..faf3d6a 100644 --- a/tests/runtime_tests/string_utility.cpp +++ b/tests/runtime_tests/string_utility.cpp @@ -343,7 +343,9 @@ TEST_CASE("append ints", "[utility]") { TEST_CASE("append floats", "[utility]") { using ae = append_test::append_expected; -#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST +#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST && SNITCH_APPEND_TO_CHARS + // answers will be different only if no bitcast AND we do have runtime to_char + // otherwise append_constexpr will be used at runtime using aed = append_test::append_expected_diff; #endif @@ -354,11 +356,16 @@ TEST_CASE("append floats", "[utility]") { CONSTEXPR_CHECK(a(0.0f) == ae{"0.000000e+00"sv, true}); #if SNITCH_CONSTEXPR_FLOAT_USE_BITCAST + // std::bit_cast is enabled, and will match the output of std::to_char if used at runtime CONSTEXPR_CHECK(a(-0.0f) == ae{"-0.000000e+00"sv, true}); -#else +#elif SNITCH_APPEND_TO_CHARS // Without std::bit_cast (or C++23), we are unable to tell the difference between -0.0f and // +0.0f in constexpr expressions. Therefore -0.0f in constexpr gets displayed as +0.0f. CONSTEXPR_CHECK(a(-0.0f) == aed{{"0.000000e+00"sv, true}, {"-0.000000e+00"sv, true}}); +#else + // No std::bit_cast, but also no std::to_char. append_constexpr will be used + // for runtime and match the compile time results + CONSTEXPR_CHECK(a(-0.0f) == ae{"0.000000e+00"sv, true}); #endif CONSTEXPR_CHECK(a(1.0f) == ae{"1.000000e+00"sv, true}); CONSTEXPR_CHECK(a(1.5f) == ae{"1.500000e+00"sv, true}); @@ -453,7 +460,7 @@ TEST_CASE("append floats", "[utility]") { TEST_CASE("append doubles", "[utility]") { using ae = append_test::append_expected; -#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST +#if !SNITCH_CONSTEXPR_FLOAT_USE_BITCAST && SNITCH_APPEND_TO_CHARS using aed = append_test::append_expected_diff; #endif @@ -464,12 +471,17 @@ TEST_CASE("append doubles", "[utility]") { CONSTEXPR_CHECK(a(0.0) == ae{"0.000000000000000e+00"sv, true}); #if SNITCH_CONSTEXPR_FLOAT_USE_BITCAST + // std::bit_cast is enabled, and will match the output of std::to_char if used at runtime CONSTEXPR_CHECK(a(-0.0) == ae{"-0.000000000000000e+00"sv, true}); -#else +#elif SNITCH_APPEND_TO_CHARS // Without std::bit_cast (or C++23), we are unable to tell the difference between -0.0f and // +0.0f in constexpr expressions. Therefore -0.0f in constexpr gets displayed as +0.0f. CONSTEXPR_CHECK( a(-0.0) == aed{{"0.000000000000000e+00"sv, true}, {"-0.000000000000000e+00"sv, true}}); +#else + // No std::bit_cast, but also no std::to_char. append_constexpr will be used for + // runtime and match the compile time results + CONSTEXPR_CHECK(a(-0.0) == ae{"0.000000000000000e+00"sv, true}); #endif CONSTEXPR_CHECK(a(1.0) == ae{"1.000000000000000e+00"sv, true}); CONSTEXPR_CHECK(a(1.5) == ae{"1.500000000000000e+00"sv, true});