21 Strings library [strings]

21.2 Character traits [char.traits]

This subclause defines requirements on classes representing character traits, and defines a class template char_­traits<charT>, along with five specializations, char_­traits<char>, char_­traits<char8_­t>, char_­traits<char16_­t>, char_­traits<char32_­t>, and char_­traits<wchar_­t>, that meet those requirements.
Most classes specified in [string.classes], [string.view], 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 typedef-names and functions in the template parameter traits used by each such template.
This subclause defines the semantics of these members.
To specialize those templates to generate a string, string view, or iostream class to handle a particular character container type ([defns.character.container]) C, that and its related character traits class X are passed as a pair of parameters to the string, string view, or iostream template as parameters charT and traits.
If X​::​char_­type is not the same type as C, the program is ill-formed.

21.2.1 Character traits requirements [char.traits.require]

In Table 69, X denotes a traits class defining types and functions for the character container type C; c and d denote values of type C; p and q denote values of type const C*; s denotes a value of type C*; n, i and j denote values of type size_­t; e and f denote values of type X​::​int_­type; pos denotes a value of type X​::​pos_­type; and r denotes an lvalue of type C.
Operations on X shall not throw exceptions.
Table 69: Character traits requirements   [tab:char.traits.req]
Expression
Return type
Assertion/note
Complexity
pre-/post-condition
X​::​char_­type
C
compile-time
X​::​int_­type
(described in [char.traits.typedefs])
compile-time
X​::​off_­type
compile-time
X​::​pos_­type
compile-time
X​::​state_­type
(described in [char.traits.typedefs])
compile-time
X​::​eq(c,d)
bool
Returns: whether c is to be treated as equal to d.
constant
X​::​lt(c,d)
bool
Returns: whether c is to be treated as less than d.
constant
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.
linear
X​::​length(p)
size_­t
Returns: the smallest i such that X​::​eq(p[i],charT()) is true.
linear
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, 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.

Returns: s.
linear
X​::​copy(s,p,n)
X​::​char_­type*
Preconditions: p not in [s, s+n).

Returns: 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).

Returns: s.
linear
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.
constant
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.
constant
X​::​to_­int_­type(c)
X​::​int_­type
Returns: some value e, constrained by the definitions of to_­char_­type and eq_­int_­type.
constant
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.
constant
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.
constant
The class template
template<class charT> struct char_traits;
is provided in the header <string> as a basis for explicit specializations.

21.2.2 Traits typedefs [char.traits.typedefs]

using int_type = see below;
Preconditions: int_­type shall be able to represent all of the valid characters converted from the corresponding char_­type values, as well as an end-of-file value, eof().221
using state_type = see below;
Preconditions: state_­type meets the Cpp17Destructible (Table 32), Cpp17CopyAssignable (Table 31), Cpp17CopyConstructible (Table 29), and Cpp17DefaultConstructible (Table 27) requirements.
If eof() can be held in char_­type then some iostreams operations can give surprising results.
⮥

21.2.3 char_­traits specializations [char.traits.specializations]

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>;
}
The header <string> defines five specializations of the class template char_­traits: char_­traits<char>, char_­traits<char8_­t>, char_­traits<char16_­t>, char_­traits<char32_­t>, and char_­traits<wchar_­t>.

21.2.3.1 struct char_­traits<char> [char.traits.specializations.char]

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;
  };
}
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 is defined identically to the built-in operator =.
The two-argument members eq and lt are defined identically to the built-in operators == and < for type unsigned char.
The member eof() returns EOF.

21.2.3.2 struct char_­traits<char8_­t> [char.traits.specializations.char8.t]

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;
  };
}
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and < respectively.
The member eof() returns an implementation-defined constant that cannot appear as a valid UTF-8 code unit.

21.2.3.3 struct char_­traits<char16_­t> [char.traits.specializations.char16.t]

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;
  };
}
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns an implementation-defined constant that cannot appear as a valid UTF-16 code unit.

21.2.3.4 struct char_­traits<char32_­t> [char.traits.specializations.char32.t]

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;
  };
}
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns an implementation-defined constant that cannot appear as a Unicode code point.

21.2.3.5 struct char_­traits<wchar_­t> [char.traits.specializations.wchar.t]

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;
  };
}
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns WEOF.