Using std::string_view with api that expects null-terminated string

13.4k views Asked by At

I have a method that takes std::string_view and uses function, which takes null terminated string as parameter. For example:

void stringFunc(std::experimental::string_view str) {
    some_c_library_func(/* Expects null terminated string */);
}

The question is, what is the proper way to handle this situation? Is str.to_string().c_str() the only option? And I really want to use std::string_view in this method, because I pass different types of strings in it.

4

There are 4 answers

3
Ralph Tandetzky On BEST ANSWER

You cannot alter a string through std::string_view. Therefore you cannot add a terminating '\0' character. Hence you need to copy the string somewhere else to add a '\0'-terminator. You could avoid heap allocations by putting the string on the stack, if it's short enough. If you know, that the std::string_view is part of a null-terminated string, then you may check, if the character past the end is a '\0' character and avoid the copy in that case. Other than that, I don't see much more room for optimizations.

5
Nicol Bolas On

I solved this problem by creating an alternate string_view class called zstring_view. It's privately inherited from string_view and contains much of its interface.

The principal difference is that zstring_view cannot be created from a string_view. Also, any string_view APIs that would remove elements from the end are not part of the interface or they return a string_view instead of a zstring_view.

They can be created from any NUL-terminated string source: std::string and so forth. I even created special user-defined literal suffixes for them: _zsv.

The idea being that, so long as you don't put a non-NUL-terminated string into zstring_view manually, all zstring_views should be NUL-terminated. Like std::string, the NUL character is not part of the size of the string, but it is there.

I find it very useful for dealing with C interfacing.

2
Paul Evans On

You certainly shouldn't call data on std::experimental::string_view:

Unlike basic_string::data() and string literals, data() may return a pointer to a buffer that is not null-terminated.

So call to_string and c_str on that:

void stringFunc(std::experimental::string_view str) {
    some_c_library_func(str.to_string().c_str());
}

or:

void stringFunc(std::experimental::string_view str) {
    std::string real_str(str);
    some_c_library_func(real_str.c_str());
}
0
Alexander Stepaniuk On

In some cases C-stype functions have overloads, which accept the length of string as a separate argument.

E.g. instead of using strcasesmp() it worth to switch to strncasecmp(). For sure, in this particular case, it would require additional logic implemented in case when strings are not equal, but the first n characters are equal.

But it could be good alternative to writing custom class for string views.