Yes, almost.
The basic_string_view design is particularly unfortunate: it's made
after C++11 and still it returns inefficient and functionality-limiting
references to characters, rather than just the values.
> it is starting to sound a bit unusable
It's not an optimal improvement compared to a different more
COW-supporting string class design. But that doesn't mean unusable. It
means the /improvement/ from a non-COW implementation is just less than
optimal, and that depending on the operations mix it can be some percent
slower or some percent faster, instead of ~always faster.
However, even within the standard's limited support there are still ways
to access the contents of a COW-implemented std::basic_string without
incurring unsharing of the buffer, including (what pops up from my
association circuits right now):
• Output to a stream.
• Indexing where the result is just used as an rvalue `Char`.
• The range based `for` loop.
I think supporting indexing with use as rvalue might possible with a
pure library implementation, by detecting the return type via `operator
auto()` (or in C++11 and earlier `operator T` with `T` a template
parameter), but if that turns out to have some problem, e.g. overload
resolution?, then it's certainly possible via the special status of the
standard library: that it can rely on compiler support and compiler
intrinsics and knowledge of the particular concrete compiler behavior,
e.g. as the standard library's `offsetof` macro necessarily does.
The range based `for` loop apparently requires compiler support, but
again, the standard library has that support.
If basic_string_view had been reasonably designed then that would also
be a way to access the contents of a COW-implemented string without
incurring a possible unsharing.
This is already pretty rich functionality for accessing the contents.
But a main thing lacking is a way to obtain a /temporary pointer/ to the
buffer, in order to pass to a function requiring such pointer. Sort of
like `c_str()` except the temporary pointer would also be invalidated by
any operation that obtained a possible reference to the string, except
for the `char` value indexing case noted above. A new version of the
standard could just introduce such an operation, so it's possible for
the standard to turn 180 degrees again and support COW.
> so I am not sure I agree with your analysis that that is
> doing COW "correctly".
As the C++03 standard put it, in its §21.3/6 (but this was non-normative
text in an inline note): “A reference counted implementation must have
the same semantics as a non-reference counted implementation.”
That effectively means /as if/ a separate buffer is used for each instance.
I.e. “correct” is defined by the external behavior always conforming to
the standard's requirements, modulo requirements that are implicitly
ignored in a given context (such as discussing whether this is possible
without the C++11 O(1) requirement on indexing). And the standard
doesn't require an implementation to be optimal! This notion of
correctness, the one specified by the standard, is the one that's
relevant in a question and answer about what the standard permits.
Cheers!,
- Alf