How you convert a std::string_view to a const char*?
Solution 1
A std::string_view
doesn't provide a conversion to a const char*
because it doesn't store a null-terminated string. It stores a pointer to the first element, and the length of the string, basically. That means that you cannot pass it to a function expecting a null-terminated string, like foo
(how else are you going to get the size?) that expects a const char*
, and so it was decided that it wasn't worth it.
If you know for sure that you have a null-terminated string in your view, you can use std::string_view::data
.
If you're not you should reconsider whether using a std::string_view
in the first place is a good idea, since if you want a guaranteed null-terminated string std::string
is what you want. For a one-liner you can use std::string(object).data()
(note: the return value points to a temporary std::string
instance that will get destroyed after the end of the expression!).
Solution 2
Simply do a std::string(string_view_object).c_str()
to get a guaranteed null-terminated temporary copy (and clean it up at the end of the line).
This is required because string view doesn't guarantee null termination. You can have a view into the middle of a longer buffer, for example.
If this use case is expensive and you have proven it to be a bottleneck, you can write an augmented string_view
that tracks if it is null terminated (basically, if it was constructed from a raw char const*
).
Then you can write a helper type that takes this augmented string_view
and either copies it to a std::string
or stores the augmented string_view
directly, and has an implicit cast-to-char const*
that returns the properly null-terminated buffer.
Then use that augmented helper type everywhere in your code base instead of string_view
, possibly augmenting string view interaction with std string as well to catch the cases where you have a view that goes to the end of the std string buffer.
But really, that is probably overkill.
A better approach is probably rewriting the APIs that take const char*
to take string_view
.
Solution 3
You can call foo(std::string(str).c_str())
.
Related videos on Youtube
Justin Raymond
Updated on January 07, 2022Comments
-
Justin Raymond over 2 years
Compiling with gcc-7.1 with the flag
-std=c++17
, the following program raises an error:#include <string_view> void foo(const char* cstr) {} void bar(std::string_view str){ foo(str); }
The error message is
In function 'void bar(std::string_view)': error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)' foo(str);
I'm surprised there is no conversion to
const char*
because other libraries (abseil, bde), provide similarstring_view
classes which implicitly convert toconst char*
.-
François Andrieux over 6 yearsMy mistake,
std::std::basic_string_view::data
does not guarantee a null terminated string.
-
-
sandthorn over 6 yearsby " (and clean it up at the end of the line).", I can continue use the member of that Rvalue til the end of scope that
std::string(string_view_object).c_str()
sitting, right? -
Yakk - Adam Nevraumont over 6 years@sandthorn No, until the end of the full expression, not scope.
-
Syndog over 5 yearsThe explanation for why std::string_view doesn't provide a conversion is great, but only offers a provisional answer to the question.
-
rems4e over 4 yearsYour recommendation about
std::string(object).data()
is a bad one, because in most cases the data will point to unallocated storage. -
Don Hatch about 4 years@rems4e An alarm went off for me as well when I saw
std::string(object).data()
recommended without the important caveat that the returned pointer is to data inside the temporary std::string object, which lasts only til the end of the largest enclosing expression. -
Ruzihm over 3 years@sandthorn If you want the string to stick around, you'd maybe prefer
std::string TempVar(string_view_object);
then where you need it in scope,TempVar.c_str()
. -
23scurtu over 2 yearsPlease remove
std::string(object).data()
from the answer or provide an easily visible warning. Thestd::string(object)
here gets deallocated, so the resulting C string is undefined. I've seen this snippet being pasted all over the internet and in various code bases. This answer has caused an immense amount of damage. -
Sahsahae about 2 yearsIt is really sad that on stack overflow we're so concerned about idiots who follow cargo cult to the T and copy paste from stack overflow for a living instead of using their brain. I don't understand, how this is even worth a consideration? You either need to pass a temporary string to some function that will do something with it for a bit, or you don't. And given the question, it is perfectly acceptable. Why should anyone care if some idiot can't read and copy pastes blindly things he doesn't even understand? Such idiot shouldn't have a job in the first place, not be shielded by SO answers.