|
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