Boost logo

Boost :

From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2021-10-16 15:02:18


Vinnie Falco wrote:
> On Fri, Oct 15, 2021 at 5:15 AM Phil Endecott via Boost
> <boost_at_[hidden]> wrote:
>> Exactly, it's like returning a string_view from a function - which
>> you should never do, at least not without an obvious indication...
>
> All functions in url_view which return encoded parts have a
> string_view return type...

Right. I think it's OK for a type whose name is *_view to have
getters that return views. Actually Arthur O'Dwyer's blog post
that I linked to before suggested that it would be OK for a
getter method of any object to return a view whose lifetime is
the same as the object - I'm not sure that I agree with that:

auto old_host = url.host();
url.set_host( new_host );
// oops, old_host is invalid because it was a view.

> How would you convert this code to use "safer parse_url(str)"?
>
> url_view u1 = parse_relative_ref( "/" ).value();
> url u2 = parse_relative_ref( "/" ).value();
> static_url<1024> u3 = parse_relative_ref( "/" ).value();
> pmr_url u4 = parse_relative_ref( "/" ).value();
> dynamic_url<
> std::allocator<char>> u5 = parse_relative_ref( "/" ).value();

There are plenty of possibilities, including:

1. Verbose names that indicate the return type.
2. Out parameters for the result.
3. Template parameter for the result type.
4. Make these constructors for the url_* types, not a free function.

These all have pros and cons, none are perfect. Here's another idea
that has just occurred to me:

5. Base the return type on the input string type. I.e. if the
input is a string_view, return a url_view; if the input is a
string with a particular allocator, return a url with the same
allocator etc. (Does this avoid all the possible nasty surprises?)

In particular, if the input is a string&&, you can move that into
the string stored by the url:

url parse_url(std::string&& s)
{
  url u;
  u.str = std::move(s);
  ... parse u.str ...
  return u;
}

In this case, if the caller writes:

auto u = parse_url( get_string_from_somewhere() );

then there is no allocation, and u is a "safe" non-view type.

This seems to work for this example:

> struct connection {
> url u_;
>
> void process( string_view s )
> {
> u_ = parse_uri( s );
> ...
> }
> };

s is a string_view, so the result of parse is a url_view, which
you can assign to the url without re-allocation (subject to capacity).

Regards, Phil


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk