
On Thu, Sep 25, 2025 at 2:34 PM Mohammad Nejati via Boost < boost@lists.boost.org> wrote:
On Thu, Sep 25, 2025 at 7:39 AM Andrzej Krzemienski via Boost <boost@lists.boost.org> wrote:
For example:
void foo(cstring_view value) { c_foo(value.c_str()); }
foo("very long string");
Would calculate the strlen for no reason.
That doesn't mean the cstring_view shouldn't calculate the size, I am just saying that my cstring_ref written specifically for this one use-case doesn't keep a size on purpose.
This is a very important observation. One "optimal" implementation of a null-terminated string_view may not be achievable.
Wouldn't adding an array constructor resolve the problem? template <size_t N> cstring_view(const char (&str)[N]);
It would solve a lot, but if we're interacting with a C-API getting a null-terminated string to pass on is not uncommon either. So not every null-terminated string in this context would have it's size known at compile time.
Keeping size as a member seems redundant, since we only use this type in an interface for two purposes: first, to make it explicit that the arguments require a null-terminated string, which also improves documentation, and second, to check the invariant that the passed string is indeed null-terminated. In practice, we just pass instances of this type as const char* to a C-API style interface that does not take a length. So what would be the use case for an O(1) size() access? Also, most use cases for null-terminated strings involve small strings, otherwise, the C-API would likely have taken a length parameter as well.
Sure, but that argument cuts both ways. That is, it's cheap enough for the constructor, but it's also cheap enough for the `size` function depending on the application. I think there are two ways to think about this: 1. a type-safe alternative to const char * (no size_t) 2. a std::string_view that guarantees a null at the end (with size_t)