245 lines
21 KiB
Markdown
245 lines
21 KiB
Markdown
[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.4 String classes"), [[string.view]](string.view "27.3 String view classes"),
|
||
and [[input.output]](input.output "31 Input/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.4 The 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.10 character 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.2 Character 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.3 Traits typedefs")) | |
|
||
| [ð](#tab:char.traits.req-row-5)<br>X::off_type | | (described in [[iostreams.limits.pos]](iostreams.limits.pos "31.2.3 Positioning type limitations") and [[iostream.forward]](iostream.forward "31.3 Forward declarations")) | |
|
||
| [ð](#tab:char.traits.req-row-6)<br>X::pos_type | | (described in [[iostreams.limits.pos]](iostreams.limits.pos "31.2.3 Positioning type limitations") and [[iostream.forward]](iostream.forward "31.3 Forward declarations")) | |
|
||
| [ð](#tab:char.traits.req-row-7)<br>X::state_type | | (described in [[char.traits.typedefs]](#typedefs "27.2.3 Traits 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.2 Header <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.2 Template 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.2 Template 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.2 Template 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.2 Template 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.2 Header <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.3 Header <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)
|