Re: C++17's string_view (was Re: Making use of move semantics?)



On 13 June 2017 at 08:31, Murray Cumming wrote:

So, I think:
1. We would use std::string_view everywhere if all the C functions took
  a length instead of assuming null-termination. That's not going to
happen.

2. Overriding all methods to take either a const char* or a std::string
(ignoring ustring for now), would avoid the extra array copy, but I
don't think it's worth it other than for methods that typically take
very large strings.

3. GTK+ functions that take very large strings tend to take a length,
to avoid the need for copying. For instance,
gtk_text_buffer_set_text(). We could take std::string_view there, but
then our use of std::string_view::to_string() would be wasteful when
someone passes a std::string to our method.

This is discouraging, so I hope I'm wrong about something.



Nope, you're correct. string_view is great if you stay in C++ world, but suboptimal when you need to pass the string to libc functions or C APIs taking null-terminated strings.

One possible approach (which I have no experience of in practice, only in theory) is to use string_view objects which explicitly include the null-terminator in their length:

template<typename C, typename T>
inline std::basic_string_view<C, T>
make_null_terminated_view(const C* s) noexcept
{ return { s, T::length() + 1 }; }

template<typename C, typename T>
inline bool
is_null_terminated_view(std::basic_string_view<C,T> sv) noexcept
{ return sv.length() && !sv.back(); }


And/or create your own cstring_view / zstring_view type which is guaranteed to be null-terminated:

struct cstring_view : std::string_view {
  cstring_view(const char* s)
  : std::string_view(s, traits_type::length(s)+1)
  { }
};

Unlike std::string which has a null-terminator after its content that isn't counted in the length, these string views would count the null character as part of their content. You'd need a little more care to use this (i.e. when using the length remember to subtract one where appropriate) but it does mean you can pass around views to null-terminated strings efficiently (along with their length, which is the advantage over a raw pointer).



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]