C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [Idea] Null-terminated string view (c_str_view / c_wstr_view) – a simpler alternative/complement to zstring_view

From: Thiago Macieira <thiago_at_[hidden]>
Date: Sat, 31 Jan 2026 21:21:49 -0800
On Saturday, 31 January 2026 18:59:28 Pacific Standard Time FPE via Std-
Proposals wrote:
> //--------------------------------------------------
> inline basic_c_str_view(const T *txt, size_t size)
> {
> if(txt[size] != (T)'\0') [[unlikely]]
> throw runtime_error("txt is not null-terminated");
>
> m_data = txt;
> m_size = size;
> }

This constructor should not exist. The size MUST be determined from the actual
string length and nothing else.

The only value of this constructor would be to throw an exception if the
actual size differs from the expected one, which I don't think is that
valuable.

> //--------------------------------------------------
> inline basic_c_str_view(basic_string_view<T> sv)
> {
> if(sv.data()[sv.size()] != (T)'\0') [[unlikely]]
> throw runtime_error("sv is not null-terminated");
>
> m_data = sv.data();
> m_size = sv.size();
> }

This constructor should not exist. Reading one-past-the-end of an arbitrary
string_view is UB and it's easy to construct an example that WILL crash.
Moreover, a basic_string_view may contain an embedded NUL, in which case the
size will differ too.

Construction from string_view is impossible to implement properly.

> //--------------------------------------------------
> inline basic_c_str_view(const basic_string<T> &str)
> {
> m_data = str.data();
> m_size = str.size();
> }

As in the plain char case, the size should be determined by strlen, not asking
the string's size, as it may include embedded NULs.

> Advantages over P3655R2 “std::zstring_view”
> -------------------------------------------
> 1. Simpler, more minimal implementation – only two data members plus a
> static empty buffer.

Why two? What's the point in keeping the size, if it can be calculated?
Compilers are good at remembering strlen() calls. Please argue for and against
it, remembering it can get out of sync if the string is changed.

> 2. Extremely low implementation burden – essentially just a thin wrapper
> with a few constructors and accessors.

So is zstring_view.

> 5. Runtime checks throw exceptions on violation – this follows modern
> engineering best practices: fail fast and visibly in debug builds rather
> than invoke undefined behavior.

As well as in release builds. In which case they have a runtime cost, which
may be undesireable. Please argue for and against in your paper.

> 6. Seamless round-trip with std::string_view via to_string_view() – users
> can freely move between the null-terminated-guarantee view and the general
> view with minimal code.

That should be in one direction only: to string_view. See above for the
construction.

> 8. Explicit wchar_t support with c_wstr_view – very helpful for Windows
> developers who frequently need null-terminated wide strings.

That would exist with zwstring_view too, if it were adopted.

> 10. No need for special “z” prefix that might confuse newcomers; aligns
> better with existing standard library naming conventions (e.g., c_str(),
> string_view).

Naming is arguable.

> 1. Is this design worth pursuing separately, or should effort be focused on
> improving P3655 (zstring_view)?

It seems to me that your only improvements are naming and the never-null
approach. Therefore, submit as an improvement over the existing proposal.

> 2. Are there any fatal flaws in the exception-throwing approach? (I chose
> exceptions for safety, but could be convinced to switch to precondition
> assertions or UB if the committee prefers.)

I don't want exceptions to be even considered in my critical cases. Therefore,
I would prefer preconditions. Those who want exceptions can turn their
compiler's contract API to exception-throwing.


-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel Data Center - Platform & Sys. Eng.

Received on 2026-02-01 05:22:07