More API details

This commit is contained in:
Victor Zverovich 2024-02-10 07:38:29 -08:00
parent 7a63e233d2
commit 91b30e5b4e
2 changed files with 25 additions and 6 deletions

View File

@ -110,15 +110,25 @@ TEST(scan_test, invalid_format) {
"invalid format string"); "invalid format string");
} }
namespace std {
using fmt::scan;
using fmt::scan_error;
}
TEST(scan_test, example) { TEST(scan_test, example) {
// Example from https://wg21.link/p1729r3. // Example from https://wg21.link/p1729r3.
if (auto result = fmt::scan<std::string, int>("answer = 42", "{} = {}")) { if (auto result = std::scan<std::string, int>("answer = 42", "{} = {}")) {
auto range = result->range();
EXPECT_EQ(range.begin(), range.end());
EXPECT_EQ(result->begin(), result->end());
#ifdef __cpp_structured_bindings #ifdef __cpp_structured_bindings
const auto& [key, value] = result->values(); const auto& [key, value] = result->values();
EXPECT_EQ(key, "answer"); EXPECT_EQ(key, "answer");
EXPECT_EQ(value, 42); EXPECT_EQ(value, 42);
#endif #endif
} else { } else {
std::scan_error error = result.error();
(void)error;
FAIL(); FAIL();
} }
} }

View File

@ -570,9 +570,10 @@ void make_args(std::array<scan_arg, sizeof...(T)>& args,
} }
} // namespace detail } // namespace detail
template <typename... T> class scan_data { template <typename Range, typename... T> class scan_data {
private: private:
std::tuple<T...> values_; std::tuple<T...> values_;
Range range_;
public: public:
scan_data() = default; scan_data() = default;
@ -589,6 +590,11 @@ template <typename... T> class scan_data {
detail::make_args<0>(args, values_); detail::make_args<0>(args, values_);
return args; return args;
} }
auto range() const -> Range { return range_; }
auto begin() const -> decltype(range_.begin()) { return range_.begin(); }
auto end() const -> decltype(range_.end()) { return range_.end(); }
}; };
template <typename... T> template <typename... T>
@ -610,10 +616,12 @@ template <typename T, typename E> class expected {
explicit operator bool() const { return has_value_; } explicit operator bool() const { return has_value_; }
auto operator->() const -> const T* { return &value_; } auto operator->() const -> const T* { return &value_; }
auto error() -> E const { return E(); }
}; };
template <typename... T> template <typename Range, typename... T>
using scan_result = expected<scan_data<T...>, scan_error>; using scan_result = expected<scan_data<Range, T...>, scan_error>;
auto vscan(string_view input, string_view fmt, scan_args args) auto vscan(string_view input, string_view fmt, scan_args args)
-> string_view::iterator { -> string_view::iterator {
@ -630,8 +638,9 @@ auto scan_to(string_view input, string_view fmt, T&... args)
} }
template <typename... T> template <typename... T>
auto scan(string_view input, string_view fmt) -> scan_result<T...> { auto scan(string_view input, string_view fmt)
auto data = scan_data<T...>(); -> scan_result<string_view, T...> {
auto data = scan_data<string_view, T...>();
vscan(input, fmt, data.make_args()); vscan(input, fmt, data.make_args());
return data; return data;
} }