From eee55917d04c812aa5b88bdd8ad071f96f0eb758 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 11 Mar 2025 17:15:02 -0600 Subject: [PATCH] Work around compiler trouble. --- source/base/utilities.cc | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/source/base/utilities.cc b/source/base/utilities.cc index 9f8b186db3..e41b50f622 100644 --- a/source/base/utilities.cc +++ b/source/base/utilities.cc @@ -662,6 +662,14 @@ namespace Utilities if ((s.size() > 0) && (s[0] == '+')) s.erase(s.begin()); + // We want to use std::from_char() to do the conversion. That's a C++17 + // function, but it turns out that some older compilers don't implement + // it correctly (notably GCC 9.x and clang 14) even though they claim + // to support C++17. We could try and test for individual compiler + // version, but it is probably enough to just select based on which C++ + // standard we are compiling with -- every compiler that supports C++20 + // should also have a complete implementation for std::from_chars(). +#ifdef DEAL_II_HAVE_CXX20 // Now convert and see whether we succeed. double d; const std::from_chars_result result = std::from_chars( @@ -681,6 +689,31 @@ namespace Utilities ExcMessage("Can't convert <" + s + "> to a double.")); return d; +#else + // Now convert and see whether we succeed. Note that strtol only + // touches errno if an error occurred, so if we want to check + // whether an error happened, we need to make sure that errno==0 + // before calling strtol since otherwise it may be that the + // conversion succeeds and that errno remains at the value it + // was before, whatever that was. + char *p; + errno = 0; + const double d = std::strtod(s.c_str(), &p); + + // We have an error if one of the following conditions is true: + // - strtod sets errno != 0 + // - The original string was empty (we could have checked that + // earlier already) + // - The string has non-zero length and strtod converted the + // first part to something useful, but stopped converting short + // of the terminating '\0' character. This happens, for example, + // if the given string is "1.234 abc". + AssertThrow(!((errno != 0) || (s.empty()) || + ((s.size() > 0) && (*p != '\0'))), + ExcMessage("Can't convert <" + s + "> to a double.")); + + return d; +#endif } -- 2.39.5