Vinnie Falco wrote:
On Fri, Oct 15, 2021 at 5:15 AM Phil Endecott via Boost
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