Skip to content

Commit 16da20f

Browse files
committed
[main] optparse: only use std::from_chars from C++20 onwards and not on Mac
See comment in the code as to why
1 parent 96210cc commit 16da20f

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

main/src/optparse.hxx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
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
}

main/src/rootbrowse.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ static RootBrowseArgs ParseArgs(const char **args, int nArgs)
7676
return outArgs;
7777
}
7878

79-
if (opts.GetBooleanFlag("help")) {
79+
if (opts.GetSwitch("help")) {
8080
outArgs.fPrintHelp = RootBrowseArgs::EPrintUsage::kLong;
8181
return outArgs;
8282
}
8383

8484
if (auto web = opts.GetFlagValue("web"); !web.empty())
8585
outArgs.fWeb = web;
8686

87-
if (opts.GetBooleanFlag("webOff"))
87+
if (opts.GetSwitch("webOff"))
8888
outArgs.fWeb = "off";
8989

9090
if (opts.GetArgs().empty())

0 commit comments

Comments
 (0)