Files
2025-10-25 03:02:53 +03:00

245 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[char.traits]
# 27 Strings library [[strings]](./#strings)
## 27.2 Character traits [char.traits]
### [27.2.1](#general) General [[char.traits.general]](char.traits.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L32)
Subclause [char.traits] defines requirements on classes representing[*character traits*](#def:character_traits),
and defines a class templatechar_traits<charT>,
along with five specializations,char_traits<char>,char_traits<char8_t>,char_traits<char16_t>,char_traits<char32_t>,
andchar_traits<wchar_t>,
that meet those requirements[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L46)
Most classes specified in [[string.classes]](string.classes "27.4String classes"), [[string.view]](string.view "27.3String view classes"),
and [[input.output]](input.output "31Input/output library") need a set of related types and functions to complete
the definition of their semantics[.](#general-2.sentence-1)
These types and functions are provided as a
set of member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")*s* and functions in the template
parameter traits used by each such template[.](#general-2.sentence-2)
Subclause [char.traits] defines the semantics of these members[.](#general-2.sentence-3)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L54)
To specialize those templates to generate a string, string view, or
iostream class to handle a particular character container type ([[defns.character.container]](defns.character.container "3.10character container type"))C,
that and its related character traits classX are passed as a pair of parameters to the string, string view, or iostream template as
parameterscharT andtraits[.](#general-3.sentence-1)
IfX::char_type is not the same type asC, the program is ill-formed[.](#general-3.sentence-2)
### [27.2.2](#require) Character traits requirements [[char.traits.require]](char.traits.require)
[1](#require-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L72)
In Table [87](#tab:char.traits.req "Table 87: Character traits requirements"),X denotes a traits class defining types and functions for the
character container typeC;c andd denote values of typeC;p andq denote values of typeconst C*;s denotes a value of typeC*;n,i andj denote values of typesize_t;e andf denote values of typeX::int_type;pos denotes a value of typeX::pos_type;
andr denotes an lvalue of typeC[.](#require-1.sentence-1)
No expression which is part of the character traits requirements
specified in [[char.traits.require]](#require "27.2.2Character traits requirements") shall exit via an exception[.](#require-1.sentence-2)
Table [87](#tab:char.traits.req) — Character traits requirements [[tab:char.traits.req]](./tab:char.traits.req)
| [🔗](#tab:char.traits.req-row-1)<br>**Expression** | **Return type** | **Assertion/note** | **Complexity** |
| --- | --- | --- | --- |
| [🔗](#tab:char.traits.req-row-2) | | **pre-/post-condition** | |
| [🔗](#tab:char.traits.req-row-3)<br>X::char_type | C | | |
| [🔗](#tab:char.traits.req-row-4)<br>X::int_type | | (described in [[char.traits.typedefs]](#typedefs "27.2.3Traits typedefs")) | |
| [🔗](#tab:char.traits.req-row-5)<br>X::off_type | | (described in [[iostreams.limits.pos]](iostreams.limits.pos "31.2.3Positioning type limitations") and [[iostream.forward]](iostream.forward "31.3Forward declarations")) | |
| [🔗](#tab:char.traits.req-row-6)<br>X::pos_type | | (described in [[iostreams.limits.pos]](iostreams.limits.pos "31.2.3Positioning type limitations") and [[iostream.forward]](iostream.forward "31.3Forward declarations")) | |
| [🔗](#tab:char.traits.req-row-7)<br>X::state_type | | (described in [[char.traits.typedefs]](#typedefs "27.2.3Traits typedefs")) | |
| [🔗](#tab:char.traits.req-row-8)<br>X::eq(c,d) | bool | *Returns*: whether c is to be treated as equal to d[.](#tab:char.traits.req-row-8-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-9)<br>X::lt(c,d) | bool | *Returns*: whether c is to be treated as less than d[.](#tab:char.traits.req-row-9-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-10)<br>X::compare(p,q,n) | int | *Returns*: 0 if for each i in [0, n), X::eq(p[i],q[i]) is true; else, a negative value if, for some j in [0, n), X::lt(p[j],q[j]) is true and for each i in [0, j) X::eq(p[i],q[i]) is true; else a positive value[.](#tab:char.traits.req-row-10-column-3-sentence-1) | linear |
| [🔗](#tab:char.traits.req-row-11)<br>X::length(p) | size_t | *Returns*: the smallest i such that X::eq(p[i],charT()) is true[.](#tab:char.traits.req-row-11-column-3-sentence-1) | linear |
| [🔗](#tab:char.traits.req-row-12)<br>X::find(p,n,c) | const X::char_type* | *Returns*: the smallest q in [p, p+n) such that X::eq(*q,c) is true, nullptr otherwise[.](#tab:char.traits.req-row-12-column-3-sentence-1) | linear |
| [🔗](#tab:char.traits.req-row-13)<br>X::move(s,p,n) | X::char_type* | for each i in [0, n), performs X::assign(s[i],p[i])[.](#tab:char.traits.req-row-13-column-3-sentence-1)<br>Copies correctly even where the ranges [p, p+n) and [s, s+n) overlap[.](#tab:char.traits.req-row-13-column-3-sentence-2)<br> *Returns*: s[.](#tab:char.traits.req-row-13-column-3-sentence-3) | linear |
| [🔗](#tab:char.traits.req-row-14)<br>X::copy(s,p,n) | X::char_type* | *Preconditions*: The ranges [p, p+n) and [s, s+n) do not overlap[.](#tab:char.traits.req-row-14-column-3-sentence-1)<br>*Returns*: s[.](#tab:char.traits.req-row-14-column-3-sentence-2)<br> for each i in [0, n), performs X::assign(s[i],p[i])[.](#tab:char.traits.req-row-14-column-3-sentence-3) | linear |
| [🔗](#tab:char.traits.req-row-15)<br>X::assign(r,d) | (not used) | assigns r=d[.](#tab:char.traits.req-row-15-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-16)<br>X::assign(s,n,c) | X::char_type* | for each i in [0, n), performs X::assign(s[i],c)[.](#tab:char.traits.req-row-16-column-3-sentence-1)<br> *Returns*: s[.](#tab:char.traits.req-row-16-column-3-sentence-2) | linear |
| [🔗](#tab:char.traits.req-row-17)<br>X::not_eof(e) | int_type | *Returns*: e if X::eq_int_type(e,X::eof()) is false, otherwise a value f such that X::eq_int_type(f,X::eof()) is false[.](#tab:char.traits.req-row-17-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-18)<br>X::to_char_type(e) | X::char_type | *Returns*: if for some c, X::eq_int_type(e,X::to_int_type(c)) is true, c; else some unspecified value[.](#tab:char.traits.req-row-18-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-19)<br>X::to_int_type(c) | X::int_type | *Returns*: some value e, constrained by the definitions of to_char_type and eq_int_type[.](#tab:char.traits.req-row-19-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-20)<br>X::eq_int_type(e,f) | bool | *Returns*: for all c and d, X::eq(c,d) is equal to X::eq_int_type(X::to_int_type(c), X::to_int_type(d)); otherwise, yields true if e and f are both copies of X::eof(); otherwise, yields false if one of e and f is a copy of X::eof() and the other is not; otherwise the value is unspecified[.](#tab:char.traits.req-row-20-column-3-sentence-1) | constant |
| [🔗](#tab:char.traits.req-row-21)<br>X::eof() | X::int_type | *Returns*: a value e such that X::eq_int_type(e,X::to_int_type(c)) is false for all values c[.](#tab:char.traits.req-row-21-column-3-sentence-1) | constant |
[2](#require-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L197)
The class template
[🔗](#lib:char_traits)
template<class charT> struct char_traits; is provided in the header [<string>](string.syn#header:%3cstring%3e "27.4.2Header <string> synopsis[string.syn]") as a basis for explicit specializations[.](#require-2.sentence-1)
### [27.2.3](#typedefs) Traits typedefs [[char.traits.typedefs]](char.traits.typedefs)
[🔗](#lib:char_type,char_traits)
`using int_type = see below;
`
[1](#typedefs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L215)
*Preconditions*: int_type shall be able to represent all of the
valid characters converted from the correspondingchar_type values, as well as an end-of-file value,eof()[.](#typedefs-1.sentence-1)[210](#footnote-210 "If eof() can be held in char_­type then some iostreams operations can give surprising results.")
[🔗](#lib:state_type,char_traits)
`using state_type = see below;
`
[2](#typedefs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L238)
*Preconditions*: state_type meets the[*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")),[*Cpp17CopyAssignable*](utility.arg.requirements#:Cpp17CopyAssignable "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [34](utility.arg.requirements#tab:cpp17.copyassignable "Table 34: Cpp17CopyAssignable requirements (in addition to Cpp17MoveAssignable)")),[*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [32](utility.arg.requirements#tab:cpp17.copyconstructible "Table 32: Cpp17CopyConstructible requirements (in addition to Cpp17MoveConstructible)")), and[*Cpp17DefaultConstructible*](utility.arg.requirements#:Cpp17DefaultConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [30](utility.arg.requirements#tab:cpp17.defaultconstructible "Table 30: Cpp17DefaultConstructible requirements")) requirements[.](#typedefs-2.sentence-1)
[210)](#footnote-210)[210)](#footnoteref-210)
Ifeof() can be held inchar_type then some iostreams operations can give surprising results[.](#footnote-210.sentence-1)
### [27.2.4](#specializations) char_traits specializations [[char.traits.specializations]](char.traits.specializations)
#### [27.2.4.1](#specializations.general) General [[char.traits.specializations.general]](char.traits.specializations.general)
[🔗](#lib:char_traits_)
namespace std {template<> struct char_traits<char>; template<> struct char_traits<char8_t>; template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; template<> struct char_traits<wchar_t>;}
[1](#specializations.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L262)
The header [<string>](string.syn#header:%3cstring%3e "27.4.2Header <string> synopsis[string.syn]") defines five specializations of the class templatechar_traits:char_traits<char>,char_traits<char8_t>,char_traits<char16_t>,char_traits<char32_t>,
andchar_traits<wchar_t>[.](#specializations.general-1.sentence-1)
#### [27.2.4.2](#specializations.char) struct char_traits<char> [[char.traits.specializations.char]](char.traits.specializations.char)
[🔗](#lib:char_traits__)
namespace std {template<> struct char_traits<char> {using char_type = char; using int_type = int; using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; };}
[1](#specializations.char-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L308)
The type mbstate_t is defined in [<cwchar>](cwchar.syn#header:%3ccwchar%3e "28.7.3Header <cwchar> synopsis[cwchar.syn]") and can represent any of the conversion states that can occur in animplementation-defined set of supported multibyte
character encoding rules[.](#specializations.char-1.sentence-1)
[2](#specializations.char-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L314)
The two-argument member assign is defined identically to the
built-in operator =[.](#specializations.char-2.sentence-1)
The two-argument members eq and lt are defined identically to the built-in operators== and < for type unsigned char[.](#specializations.char-2.sentence-2)
[3](#specializations.char-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L320)
The membereof() returnsEOF[.](#specializations.char-3.sentence-1)
#### [27.2.4.3](#specializations.char8.t) struct char_traits<char8_t> [[char.traits.specializations.char8.t]](char.traits.specializations.char8.t)
[🔗](#lib:char_traits___)
namespace std {template<> struct char_traits<char8_t> {using char_type = char8_t; using int_type = unsigned int; using off_type = streamoff; using pos_type = u8streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; };}
[1](#specializations.char8.t-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L359)
The two-argument members assign, eq, and lt are defined identically to
the built-in operators =, ==, and < respectively[.](#specializations.char8.t-1.sentence-1)
[2](#specializations.char8.t-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L364)
The member eof() returns animplementation-defined constant
that cannot appear as a valid UTF-8 code unit[.](#specializations.char8.t-2.sentence-1)
#### [27.2.4.4](#specializations.char16.t) struct char_traits<char16_t> [[char.traits.specializations.char16.t]](char.traits.specializations.char16.t)
[🔗](#lib:char_traits____)
namespace std {template<> struct char_traits<char16_t> {using char_type = char16_t; using int_type = uint_least16_t; using off_type = streamoff; using pos_type = u16streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; };}
[1](#specializations.char16.t-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L405)
The two-argument members assign,eq, and lt are defined identically to
the built-in operators =, ==, and<, respectively[.](#specializations.char16.t-1.sentence-1)
[2](#specializations.char16.t-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L411)
The member eof() returns animplementation-defined constant that cannot appear
as a valid UTF-16 code unit[.](#specializations.char16.t-2.sentence-1)
#### [27.2.4.5](#specializations.char32.t) struct char_traits<char32_t> [[char.traits.specializations.char32.t]](char.traits.specializations.char32.t)
[🔗](#lib:char_traits_____)
namespace std {template<> struct char_traits<char32_t> {using char_type = char32_t; using int_type = uint_least32_t; using off_type = streamoff; using pos_type = u32streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; };}
[1](#specializations.char32.t-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L451)
The two-argument members assign,eq, and lt are defined identically to
the built-in operators =, ==, and<, respectively[.](#specializations.char32.t-1.sentence-1)
[2](#specializations.char32.t-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L457)
The member eof() returns animplementation-defined constant that cannot appear as a Unicode
code point[.](#specializations.char32.t-2.sentence-1)
#### [27.2.4.6](#specializations.wchar.t) struct char_traits<wchar_t> [[char.traits.specializations.wchar.t]](char.traits.specializations.wchar.t)
[🔗](#lib:char_traits______)
namespace std {template<> struct char_traits<wchar_t> {using char_type = wchar_t; using int_type = wint_t; using off_type = streamoff; using pos_type = wstreampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; };}
[1](#specializations.wchar.t-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L497)
The two-argument membersassign,eq,
andlt are defined identically
to the built-in operators=,==,
and<,
respectively[.](#specializations.wchar.t-1.sentence-1)
[2](#specializations.wchar.t-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L511)
The membereof() returnsWEOF[.](#specializations.wchar.t-2.sentence-1)