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(
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
}