diff --git a/examples/readme_examples.cpp b/examples/readme_examples.cpp index 92853c5..db891e3 100644 --- a/examples/readme_examples.cpp +++ b/examples/readme_examples.cpp @@ -213,6 +213,11 @@ bool basis_operation() { | std::ranges::to()}; return to_utf8_1 == to_utf8_2; } + +static_assert( + !std::ranges::equal(u8"foo" | to_utf32, std::array{U'f', U'o', U'o', U'\0'})); +static_assert( + std::ranges::equal(u8"foo" | to_utf32, std::array{U'f', U'o', U'o'})); #endif bool readme_examples() { diff --git a/paper/P2728.md b/paper/P2728.md index 80c9f55..2ac491e 100644 --- a/paper/P2728.md +++ b/paper/P2728.md @@ -286,6 +286,27 @@ The table below compares the error handling behavior of the `to_utf16` and ![](../../paper/images/error_handling.png){ width=750px } +### Special CPO Logic for String Literals + +The `to_utfN` CPOs use a heuristic to detect null-terminated ranges and omit +the null terminator so that it doesn't appear in the output. If the input +range satisfies `is_bounded_array_v`, is nonempty, and its last element is 0, +then the last element is omitted. + +Without this logic, you'd have: + +```c++ +static_assert( + std::ranges::equal(u8"foo" | to_utf32, std::array{U'f', U'o', U'o', U'\0'})); +``` + +Instead, with the heuristic in place, the null terminator is eliminated: + +```c++ +static_assert( + std::ranges::equal(u8"foo" | to_utf32, std::array{U'f', U'o', U'o'})); +``` + ### The `_or_error` Views Are Basis Operations for Other Error Handling Behaviors You can use the `_or_error` view to implement the same behavior that the