This subclause defines requirements on classes representing
character traits,
and defines a class template
char_traits<charT>,
along with four specializations,
char_traits<char>,
char_traits<char16_t>,
char_traits<char32_t>,
and
char_traits<wchar_t>,
that satisfy those requirements.
Most classes specified in Clauses [string.classes] and [input.output] need a set of related types and functions to complete the definition of their semantics. These types and functions are provided as a set of member typedefs and functions in the template parameter `traits' used by each such template. This subclause defines the semantics guaranteed by these members.
To specialize those templates to generate a string or iostream class to handle a particular character container type CharT, that and its related character traits class Traits are passed as a pair of parameters to the string or iostream template as formal parameters charT and traits. Traits::char_type shall be the same as CharT.
This subclause specifies a struct template, char_traits<charT>, and four explicit specializations of it, char_traits<char>, char_traits<char16_t>, char_traits<char32_t>, and char_traits<wchar_t>, all of which appear in the header <string> and satisfy the requirements below.
In Table [tab:char.traits.require], X denotes a Traits class defining types and functions for the character container type CharT; c and d denote values of type CharT; p and q denote values of type const CharT*; s denotes a value of type CharT*; n, i and j denote values of type std::size_t; e and f denote values of type X::int_type; pos denotes a value of type X::pos_type; state denotes a value of type X::state_type; and r denotes an lvalue of type CharT. Operations on Traits shall not throw exceptions.
Expression | Return type | Assertion/note | Complexity |
pre-/post-condition | |||
X::char_type | charT | (described in [char.traits.typedefs]) | compile-time |
X::int_type | (described in [char.traits.typedefs]) | compile-time | |
X::off_type | (described in [char.traits.typedefs]) | compile-time | |
X::pos_type | (described in [char.traits.typedefs]) | compile-time | |
X::state_type | (described in [char.traits.typedefs]) | compile-time | |
X::eq(c,d) | bool | yields: whether c is to be treated as equal to d. | constant |
X::lt(c,d) | bool | yields: whether c is to be treated as less than d. | constant |
X::compare(p,q,n) | int | yields: 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. | linear |
X::length(p) | std::size_t | yields: the smallest i such that X::eq(p[i],charT()) is true. | linear |
X::find(p,n,c) | const X::char_type* | yields: the smallest q in [p,p+n) such that X::eq(*q,c) is true, zero otherwise. | linear |
X::move(s,p,n) | X::char_type* | for each i in [0,n), performs X::assign(s[i],p[i]). Copies correctly even where the ranges [p,p+n) and [s,s+n) overlap. yields: s. | linear |
X::copy(s,p,n) | X::char_type* | pre: p not in [s,s+n). yields: s. for each i in [0,n), performs X::assign(s[i],p[i]). | linear |
X::assign(r,d) | (not used) | assigns r=d. | constant |
X::assign(s,n,c) | X::char_type* | for each i in [0,n), performs X::assign(s[i],c). yields: s. | linear |
X::not_eof(e) | int_type | yields: 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. | constant |
X::to_char_type(e) | X::char_type | yields: if for some c, X::eq_int_type(e,X::to_int_type(c)) is true, c; else some unspecified value. | constant |
X::to_int_type(c) | X::int_type | yields: some value e, constrained by the definitions of to_char_type and eq_int_type. | constant |
X::eq_int_type(e,f) | bool | yields: 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. | constant |
X::eof() | X::int_type | yields: a value e such that X::eq_int_type(e,X::to_int_type(c)) is false for all values c. | constant |
The struct template
template<class charT> struct char_traits;
shall be provided in the header <string> as a basis for explicit specializations.
The type char_type is used to refer to the character container type in the implementation of the library classes defined in [string.classes] and Clause [input.output].
Requires: For a certain character container type char_type, a related container type INT_T shall be a type or class which can represent all of the valid characters converted from the corresponding char_type values, as well as an end-of-file value, eof(). The type int_type represents a character container type which can hold end-of-file to be used as a return type of the iostream class member functions.233
typedef implementation-defined off_type;
typedef implementation-defined pos_type;
Requires: Requirements for off_type and pos_type are described in [iostreams.limits.pos] and [iostream.forward].
Requires: state_type shall meet the requirements of CopyAssignable (Table [copyassignable]), CopyConstructible (Table [copyconstructible]), and DefaultConstructible (Table [defaultconstructible]) types.
If eof() can be held in char_type then some iostreams operations may give surprising results.
namespace std { template<> struct char_traits<char>; template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; template<> struct char_traits<wchar_t>; }
The header <string> shall define four specializations of the template struct char_traits: char_traits<char>, char_traits<char16_t>, char_traits<char32_t>, and char_traits<wchar_t>.
The requirements for the members of these specializations are given in Clause [char.traits.require].
namespace std { template<> struct char_traits<char> { typedef char char_type; typedef int int_type; typedef streamoff off_type; typedef streampos pos_type; typedef mbstate_t state_type; static 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 int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static 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; }; }
The defined types for int_type, pos_type, off_type, and state_type shall be int, streampos, streamoff, and mbstate_t respectively.
The type streampos shall be an implementation-defined type that satisfies the requirements for pos_type in [iostreams.limits.pos] and [iostream.forward].
The type streamoff shall be an implementation-defined type that satisfies the requirements for off_type in [iostreams.limits.pos] and [iostream.forward].
The type mbstate_t is defined in <cwchar> and can represent any of the conversion states that can occur in an implementation-defined set of supported multibyte character encoding rules.
The two-argument member assign shall be defined identically to the built-in operator =. The two-argument members eq and lt shall be defined identically to the built-in operators == and < for type unsigned char.
The member eof() shall return EOF.
namespace std { template<> struct char_traits<char16_t> { typedef char16_t char_type; typedef uint_least16_t int_type; typedef streamoff off_type; typedef u16streampos pos_type; typedef mbstate_t state_type; static 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 int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static 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; }; }
The type u16streampos shall be an implementation-defined type that satisfies the requirements for pos_type in [iostreams.limits.pos] and [iostream.forward].
The two-argument members assign, eq, and lt shall be defined identically to the built-in operators =, ==, and < respectively.
namespace std { template<> struct char_traits<char32_t> { typedef char32_t char_type; typedef uint_least32_t int_type; typedef streamoff off_type; typedef u32streampos pos_type; typedef mbstate_t state_type; static 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 int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static 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; }; }
The type u32streampos shall be an implementation-defined type that satisfies the requirements for pos_type in [iostreams.limits.pos] and [iostream.forward].
The two-argument members assign, eq, and lt shall be defined identically to the built-in operators =, ==, and < respectively.
namespace std { template<> struct char_traits<wchar_t> { typedef wchar_t char_type; typedef wint_t int_type; typedef streamoff off_type; typedef wstreampos pos_type; typedef mbstate_t state_type; static 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 int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static 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; }; }
The defined types for int_type, pos_type, and state_type shall be wint_t, wstreampos, and mbstate_t respectively.
The type wstreampos shall be an implementation-defined type that satisfies the requirements for pos_type in [iostreams.limits.pos] and [iostream.forward].
The type mbstate_t is defined in <cwchar> and can represent any of the conversion states that can occur in an implementation-defined set of supported multibyte character encoding rules.
The two-argument members assign, eq, and lt shall be defined identically to the built-in operators =, ==, and < respectively.
The member eof() shall return WEOF.