5656#include < charconv>
5757#include < cstring>
5858#include < iostream>
59+ #include < limits>
5960#include < optional>
6061#include < sstream>
6162#include < stdexcept>
@@ -208,9 +209,14 @@ public:
208209 static_assert (std::is_integral_v<T> || std::is_floating_point_v<T>);
209210
210211 if (auto val = GetFlagValue (name); !val.empty ()) {
212+ // NOTE: on paper std::from_chars is supported since C++17, however some compilers don't properly support it
213+ // (e.g. it's not available at all on MacOS < 26 and only the integer overload is available in AlmaLinux 8).
214+ // There is also no compiler define that we can use to determine the availability, so we just use it only
215+ // from C++20 and hope for the best.
216+ #if __cplusplus >= 202002L && !defined(R__MACOSX)
211217 T converted;
212218 auto res = std::from_chars (val.data (), val.data () + val.size (), converted);
213- if (res.ptr == val.end () && res.ec == std::errc{}) {
219+ if (res.ptr == val.data () + val. size () && res.ec == std::errc{}) {
214220 return converted;
215221 } else {
216222 std::stringstream err;
@@ -225,6 +231,32 @@ public:
225231 else
226232 throw std::invalid_argument (err.str ());
227233 }
234+ #else
235+ std::conditional_t <std::is_integral_v<T>, long long , long double > converted;
236+ std::size_t unconvertedPos;
237+ if constexpr (std::is_integral_v<T>) {
238+ converted = std::stoll (std::string (val), &unconvertedPos);
239+ } else {
240+ converted = std::stold (std::string (val), &unconvertedPos);
241+ }
242+
243+ const bool isOor = converted > std::numeric_limits<T>::max ();
244+ if (unconvertedPos != val.size () || isOor) {
245+ std::stringstream err;
246+ err << " Failed to parse flag `" << name << " ` with value `" << val << " `" ;
247+ if constexpr (std::is_integral_v<T>)
248+ err << " as an integer.\n " ;
249+ else
250+ err << " as a floating point number.\n " ;
251+
252+ if (isOor)
253+ throw std::out_of_range (err.str ());
254+ else
255+ throw std::invalid_argument (err.str ());
256+ }
257+
258+ return converted;
259+ #endif
228260 }
229261 return std::nullopt ;
230262 }
0 commit comments