Seriously, whats't up. There is an implicit conversion from std::string
to std::string_view
and it's not considered unsafe. Even though this surely may cause a lot of dangling references if programmer is not careful.
On the other hand, they have dismissed an implicit conversion from std::string_view
to std::string
using same argument but in completely opposite fashion: because programmer may be not careful.
It's lovely that they have created a replacement for a raw const char*
pointer while making it super confusing and stripped to the bone:
- Implicit
const char*
->std::string
: OK - Implicit
std::string_view
->std::string
: NOPE - Assignment
std::string
=const char*
: OK - Assignment
std::string
=std::string_view
: OK - Appending
std::string
+=const char*
: OK - Appending
std::string
+=std::string_view
: OK - Concatenation
const char*
+std::string
: OK - Concatenation
std::string_view
+std::string
: NOPE - Concatenation
std::string
+const char*
: OK - Concatenation
std::string
+std::string_view
: NOPE
Am I missing something or is this a total nonsense?
In the end, how useful is this string view without all the crucial pieces that make it similar to const char*
? What's the point of integrating it into the ecosystem of stdlib while not making the last step to make it complete? After all, if we would just need an object that represents a piece of a string we could write our own. Actually, a lot of libraries already did, years ago. The whole point of making something standard is to make it useful for widest range of use cases, isn't it?
Are they going to fix this in C++2a?
The problem is that
std::string_view
->std::string
makes a copy of the underlying memory, complete with heap allocation, whereas the implicitstd::string
->std::string_view
does not. If you've bothered to use astd::string_view
in the first place then you obviously care about copies, so you don't want one to happen implicitly.Consider this example:
The function
foo2
could've used aconst std::string&
parameter, but used astd::string_view
so that it is more efficient if you pass in a string that isn't astd::string
; no surprises there. But it's less efficient than if you'd just given it aconst std::string&
parameter!foo2
is called with astd::string
argument (e.g. byfoo1
): Whenfoo2
callsfoo3
, it creates a copy of the string. If it had aconst std::string&
argument, it could've used the object it already had.foo2
is called with aconst char*
argument: Astd::string
copy has to be made sooner or later; with aconst std::string&
parameter it gets made earlier, but overall there's exactly one copy either way.Now imagine
foo2
calls multiple functions likefoo3
, or callsfoo3
in a loop; it's making exactly the samestd::string
object over and over. You'd want the compiler to notify you about this.