hanickadot / compile-time-regular-expressions

Compile Time Regular Expression in C++
https://twitter.com/hankadusikova
Apache License 2.0
3.22k stars 177 forks source link

interface with `std::optional` #302

Closed TheClonerx closed 5 months ago

TheClonerx commented 5 months ago

I always keep finding myself converting optional captures (ie. ([abcdef]+)?) to std::optionals with something like the following:

auto to_optional = [](auto const &capture) -> std::optional<std::string_view> {
  if (capture)
    return capture.view();
  else
    return std::nullopt;
};

auto const maybe_foo = to_optional(match_result.template get<1>());

I think it would be a good idea to add this functionality directly to the regex_results class template.

hanickadot commented 5 months ago

regex_results is already optional "like" type. I wonder how are you using optional<std::string_view> which is not contained in the regex_results. I do think about changing this part of API, but I would like to learn more about other's use-cases, thanks.

TheClonerx commented 5 months ago

I convert them to std::optional in order to return the results in struct members rather an regex_results. Take this as an example:

struct UserInfo {
  std::string_view user;
  std::optional<std::string_view> password;
};

std::optional<UserInfo> parse_userinfo(std::string_view str) {
  if (auto const &&[match, user, password] = ctre::match<"([a-z]+)(?::(.*))?">(str); match)
    return UserInfo{ .user=user.view, .password=to_optional(password), };
  else
    return std::nullopt;
}
hanickadot commented 5 months ago

ok, I would worry a bit about having views in some data structure tied to original input, but I can see usefulness of this

TheClonerx commented 5 months ago

I would worry a bit about having views in some data structure tied to original input,

Of course it doesn't have to be for just std::string_view, ideally this would be implemented for std::string and numbers, making them analogous to the to_view(), to_string(), and to_number() member functions.

hanickadot commented 5 months ago

fixed in 9725886582a928491a086bba1c07909b2e583157

added functions to_optional_view(), to_optional_string(), and to_optional_number() also added conversion operators for std::optional<std::basic_string_view<char_type>> and std::optional<std::basic_string<char_type>> (explicit)

hanickadot commented 5 months ago

https://compiler-explorer.com/z/zMecxGvsM

hanickadot commented 5 months ago

I like this pattern:

std::optional<std::string_view> parse(std::string_view input) {
    return ctre::match<"[a-f]+">(input);
}
hanickadot commented 5 months ago

FYI: it was already implicitly convertible to string_view, so in your example, you can just write:

struct UserInfo {
  std::string_view user;
  std::optional<std::string_view> password;
};

std::optional<UserInfo> parse_userinfo(std::string_view str) {
  if (auto const &&[match, user, password] = ctre::match<"([a-z]+)(?::(.*))?">(str); match)
    return UserInfo{ .user=user, .password=password };
  else
    return std::nullopt;
}
hanickadot commented 5 months ago

Out of topic: I hope we will one day get rid of the ; match) at end of the if

TheClonerx commented 5 months ago

Wow that was fast! Much appreciated.

it was already implicitly convertible to string_view

I'm aware, I just prefer explicit conversions. :)