C++ Logo

std-proposals

Advanced search

Re: missing operator + and += overloads for std::string_view

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 10 Aug 2020 10:23:38 -0400
On Mon, Aug 10, 2020 at 9:40 AM Dominic Fandrey via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> I think it is probably an oversight and not intentional that those are not
> there:
>
> constexpr std::string operator +(std::string const &, std::string_view
> const &);
> constexpr std::string operator +(std::string_view const &, std::string
> const &);
> constexpr std::string operator +=(std::string &, std::string_view const &);
>
> I would even hope for this one:
>
> constexpr std::string operator +(std::string_view const &,
> std::string_view const &);
>

I should write a blog post about this one at some point.
See also
https://www.reddit.com/r/cpp/comments/9bwou7/why_doesnt_stdfilesystempath_have_an_operator/
https://stackoverflow.com/questions/46137433/why-do-boostfilesystempath-and-stdfilesystempath-lack-operator

The reasons I'm currently aware of are:
- Overload resolution ambiguity. In C++98, the idiom was to provide
foo(const string&) and foo(const char*) as an overload set. In C++17, the
idiom is to provide foo(string_view) as the only overload. If you provide
all three, then theoretically you might ambiguate old callers where the
argument type is convertible to both string and string_view. (But how could
this happen in old code? I don't know.) You would also ambiguate old calls
like `foo({"abc", 3})`, but such calls are obvious abominations anyway.
(Implicit conversions are the devil!)
Here's a Godbolt showing that the common cases I can think of are *not*
ambiguated: https://godbolt.org/z/Gbjssc

- For the fourth: Avoiding quiet memory allocation. There is an idiom
(which I've never used, but I heard it from Mathias Stearn) where a certain
subsystem of your codebase does absolutely everything in terms of
non-owning string_views into a buffer that is owned by the subsystem's
caller. In this idiom, it is an essential feature that there's nothing you
can do accidentally with a `string_view` to turn it back into an owning
string. You just write your code as if you were using strings — you can
store your string_views in containers, use them as map keys, use them as
local variables, whatever — and as long as you remember to always use
`auto` or `string_view` instead of `string`, your code should work
correctly. If `a + b` could quietly return a `string`, then this would all
fall down.

- For the fourth: Avoiding quiet memory allocation, part 2. Consider `using
T = string_view; T a, b; T ab = a + b;`. The string_view `ab` dangles
immediately upon construction. That's not good. In particular,
`std::accumulate` over a range of string_views would have awful runtime
behavior. (There are several different possible solutions and
half-solutions here, but clearly "just don't provide operator+ for
string_views" is the easiest solution.)

For the first three, the argument I listed is pretty weak. But combine that
with the rapid release cycle — only a year or two to work on the feature
before it was frozen — compounded with the committee's knowledge that they
were *also* shipping filesystem::path in the same release, and I think
"mild uncertainty about overload resolution" could easily translate into "a
majority of voters agree, maybe it's safer to just remove the operator+ for
now."

Still, I suspect I'm missing at least one, maybe two, other reasons not to
support `string += string_view`. Anyone got any?

–Arthur

Received on 2020-08-10 09:27:13