Using std::string_view with api, what expects null terminated string

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.


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.


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());
}

Tags:

C++

C++17