P3688R6 — ASCII character utilities
(7 items)
LEWG
This paper proposes a new header providing locale-independent, constexpr character testing and transformation functions for all five C++ character types (char, wchar_t, char8_t, char16_t, char32_t). The proposed functions (e.g., ascii_is_digit, ascii_is_alphabetic, ascii_to_lower, ascii_case_insensitive_compare) address deficiencies in and , including lack of constexpr support, no Unicode character type support, locale dependence, and undefined behavior pitfalls. All functions treat their input as ASCII-encoded regardless of the literal encoding, returning false or identity results for non-ASCII code units.
- §3.9 — Example uses ranges::find with a lambda predicate, but ranges::find searches by value, not predicate. The expression is ill-formed; should be ranges::find_if. [1]
- §3.5 — ascii_case_insensitive_equals is declared returning strong_ordering in the design discussion code, but the body returns the result of ==, which is bool. The wording synopsis correctly has bool. [2]
- §4 — Parenthetical '(as proposed)' implies the paper proposes overload sets, but since R5 the design uses function templates. The implementation-experience text is stale. [3]
- §3.8.2 — Both naming schemes in the contrast are written as is_ascii_*; one should be ascii_is_* to actually contrast the two options. [4]
- §3.8.2 — 'rests' is a misspelling of 'tests'. [5]
References — Anthropic Citations API
[1]
"constexpr strong_ordering ascii_case_insensitive_equals(T a, T b) { return ascii_to_upper(a) == ascii_to_upper(b); }"
"constexpr strong_ordering ascii_case_insensitive_equals(T a, T b) { return ascii_to_upper(a) == ascii_to_upper(b); }"
[2]
"R4 and previous revisions of this paper used the naming scheme is_ascii_* rather than is_ascii_* for character rests."
"R4 and previous revisions of this paper used the naming scheme is_ascii_* rather than is_ascii_* for character rests."
[3]
chars 117924–118121
"ascii_is_* vs. is_ascii_*
"
R4 and previous revisions of this paper used the naming scheme
[3]
chars 117924–118121
"ascii_is_* vs. is_ascii_*
"
R4 and previous revisions of this paper used the naming scheme
[4]
"auto it = std::ranges::find(str, [](char8_t c) { return std::ascii_is_digit(c); });"
"auto it = std::ranges::find(str, [](char8_t c) { return std::ascii_is_digit(c); });"
[5]
"A naive implementation of all proposed functions can be found at [CompilerExplorer], although these are implemented as function templates, not as overload sets (as proposed)."
"A naive implementation of all proposed functions can be found at [CompilerExplorer], although these are implemented as function templates, not as overload sets (as proposed)."
Summary: P3688R6 proposes a set of ASCII character classification and transformation utilities (ascii_is_digit, ascii_to_upper, etc.) as function templates in a new header, intended to replace the legacy functions with type-safe, locale-independent alternatives. Five defects were found, including an incorrect return type in design discussion code, a code example that would not compile, and a stale reference to the pre-R5 overload-set design.
Pipeline: Discovery (Anthropic Opus + Citations API) → Verification Gate (OpenRouter Opus) → Report Writer (OpenRouter Opus)
Provenance: All references are machine-verified character positions from the Anthropic Citations API — deterministic, exact substrings, not model-generated quotes.
Provenance: All references are machine-verified character positions from the Anthropic Citations API — deterministic, exact substrings, not model-generated quotes.