[category.ctype]

# 28 Text processing library [[text]](./#text)

## 28.3 Localization library [[localization]](localization#category.ctype)

### 28.3.4 Standard locale categories [[locale.categories]](locale.categories#category.ctype)

#### 28.3.4.2 The ctype category [category.ctype]

#### [28.3.4.2.1](#general) General [[category.ctype.general]](category.ctype.general)

[ð](#lib:ctype_base)

namespace std {class ctype_base {public:using mask = *see below*; // numeric values are for exposition only.static constexpr mask space = 1 << 0; static constexpr mask print = 1 << 1; static constexpr mask cntrl = 1 << 2; static constexpr mask upper = 1 << 3; static constexpr mask lower = 1 << 4; static constexpr mask alpha = 1 << 5; static constexpr mask digit = 1 << 6; static constexpr mask punct = 1 << 7; static constexpr mask xdigit = 1 << 8; static constexpr mask blank = 1 << 9; static constexpr mask alnum = alpha | digit; static constexpr mask graph = alnum | punct; };}

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1343)

The type mask is a bitmask type ([[bitmask.types]](bitmask.types "16.3.3.3.3 Bitmask types"))[.](#general-1.sentence-1)

#### [28.3.4.2.2](#locale.ctype) Class template ctype [[locale.ctype]](locale.ctype)

#### [28.3.4.2.2.1](#locale.ctype.general) General [[locale.ctype.general]](locale.ctype.general)

[ð](#lib:ctype)

namespace std {template<class charT>class ctype : public locale::facet, public ctype_base {public:using char_type = charT; explicit ctype(size_t refs = 0); bool is(mask m, charT c) const; const charT* is(const charT* low, const charT* high, mask* vec) const; const charT* scan_is(mask m, const charT* low, const charT* high) const; const charT* scan_not(mask m, const charT* low, const charT* high) const;
 charT toupper(charT c) const; const charT* toupper(charT* low, const charT* high) const;
 charT tolower(charT c) const; const charT* tolower(charT* low, const charT* high) const;

 charT widen(char c) const; const char* widen(const char* low, const char* high, charT* to) const; char narrow(charT c, char dfault) const; const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; static locale::id id; protected:~ctype(); virtual bool do_is(mask m, charT c) const; virtual const charT* do_is(const charT* low, const charT* high, mask* vec) const; virtual const charT* do_scan_is(mask m, const charT* low, const charT* high) const; virtual const charT* do_scan_not(mask m, const charT* low, const charT* high) const; virtual charT do_toupper(charT) const; virtual const charT* do_toupper(charT* low, const charT* high) const; virtual charT do_tolower(charT) const; virtual const charT* do_tolower(charT* low, const charT* high) const; virtual charT do_widen(char) const; virtual const char* do_widen(const char* low, const char* high, charT* dest) const; virtual char do_narrow(charT, char dfault) const; virtual const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const; };}

[1](#locale.ctype.general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1395)

Class ctype encapsulates the C library [<cctype>](cctype.syn#header:%3ccctype%3e "28.7.1 Header <cctype> synopsis [cctype.syn]") features[.](#locale.ctype.general-1.sentence-1)

istream members are required to use ctype<> for character classing during input parsing[.](#locale.ctype.general-1.sentence-2)

[2](#locale.ctype.general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1400)

The specializations
required in Table [91](locale.category#tab:locale.category.facets "Table 91: Locale category facets") ([[locale.category]](locale.category "28.3.3.1.2.1 Type locale​::​category")),
namely ctype<char> and ctype<wchar_t>,
implement character classing appropriate
to the implementation's native character set[.](#locale.ctype.general-2.sentence-1)

#### [28.3.4.2.2.2](#locale.ctype.members) ctype members [[locale.ctype.members]](locale.ctype.members)

[ð](#lib:ctype,is)

`bool         is(mask m, charT c) const;
const charT* is(const charT* low, const charT* high, mask* vec) const;
`

[1](#locale.ctype.members-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1416)

*Returns*: do_is(m, c) or do_is(low, high, vec)[.](#locale.ctype.members-1.sentence-1)

[ð](#lib:ctype,scan_is)

`const charT* scan_is(mask m, const charT* low, const charT* high) const;
`

[2](#locale.ctype.members-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1427)

*Returns*: do_scan_is(m, low, high)[.](#locale.ctype.members-2.sentence-1)

[ð](#lib:ctype,scan_not)

`const charT* scan_not(mask m, const charT* low, const charT* high) const;
`

[3](#locale.ctype.members-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1438)

*Returns*: do_scan_not(m, low, high)[.](#locale.ctype.members-3.sentence-1)

[ð](#lib:ctype,toupper)

`charT        toupper(charT c) const;
const charT* toupper(charT* low, const charT* high) const;
`

[4](#locale.ctype.members-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1450)

*Returns*: do_toupper(c) or do_toupper(low, high)[.](#locale.ctype.members-4.sentence-1)

[ð](#lib:ctype,tolower)

`charT        tolower(charT c) const;
const charT* tolower(charT* low, const charT* high) const;
`

[5](#locale.ctype.members-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1462)

*Returns*: do_tolower(c) or do_tolower(low, high)[.](#locale.ctype.members-5.sentence-1)

[ð](#lib:ctype,widen)

`charT       widen(char c) const;
const char* widen(const char* low, const char* high, charT* to) const;
`

[6](#locale.ctype.members-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1474)

*Returns*: do_widen(c) or do_widen(low, high, to)[.](#locale.ctype.members-6.sentence-1)

[ð](#lib:ctype,narrow)

`char         narrow(charT c, char dfault) const;
const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const;
`

[7](#locale.ctype.members-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1486)

*Returns*: do_narrow(c, dfault) or do_narrow(low, high, dfault, to)[.](#locale.ctype.members-7.sentence-1)

#### [28.3.4.2.2.3](#locale.ctype.virtuals) ctype virtual functions [[locale.ctype.virtuals]](locale.ctype.virtuals)

[ð](#lib:ctype,do_is)

`bool         do_is(mask m, charT c) const;
const charT* do_is(const charT* low, const charT* high, mask* vec) const;
`

[1](#locale.ctype.virtuals-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1500)

*Effects*: Classifies a character or sequence of characters[.](#locale.ctype.virtuals-1.sentence-1)

For each argument character,
identifies a value M of type ctype_base​::​mask[.](#locale.ctype.virtuals-1.sentence-2)

The second form identifies a value M of type ctype_base​::​mask for each *p where (low <= p && p < high),
and places it into vec[p - low][.](#locale.ctype.virtuals-1.sentence-3)

[2](#locale.ctype.virtuals-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1509)

*Returns*: The first form returns the result of the expression (M & m) != 0;
i.e., true if the character has the characteristics specified[.](#locale.ctype.virtuals-2.sentence-1)

The second form returns high[.](#locale.ctype.virtuals-2.sentence-2)

[ð](#lib:ctype_base,do_scan_is)

`const charT* do_scan_is(mask m, const charT* low, const charT* high) const;
`

[3](#locale.ctype.virtuals-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1522)

*Effects*: Locates a character in a buffer that conforms to a classification m[.](#locale.ctype.virtuals-3.sentence-1)

[4](#locale.ctype.virtuals-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1526)

*Returns*: The smallest pointer p in the range [low, high)
such that is(m, *p) would return true;
otherwise, returns high[.](#locale.ctype.virtuals-4.sentence-1)

[ð](#lib:ctype,do_scan_not)

`const charT* do_scan_not(mask m, const charT* low, const charT* high) const;
`

[5](#locale.ctype.virtuals-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1539)

*Effects*: Locates a character in a buffer that fails to conform to a classificationm[.](#locale.ctype.virtuals-5.sentence-1)

[6](#locale.ctype.virtuals-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1544)

*Returns*: The smallest pointer p, if any, in the range [low, high)
such that is(m, *p) would return false;
otherwise, returns high[.](#locale.ctype.virtuals-6.sentence-1)

[ð](#lib:ctype,do_toupper)

`charT        do_toupper(charT c) const;
const charT* do_toupper(charT* low, const charT* high) const;
`

[7](#locale.ctype.virtuals-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1558)

*Effects*: Converts a character or characters to upper case[.](#locale.ctype.virtuals-7.sentence-1)

The second form replaces
each character *p in the range [low, high)
for which a corresponding upper-case character exists,
with that character[.](#locale.ctype.virtuals-7.sentence-2)

[8](#locale.ctype.virtuals-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1566)

*Returns*: The first form returns
the corresponding upper-case character if it is known to exist, or
its argument if not[.](#locale.ctype.virtuals-8.sentence-1)

The second form returns high[.](#locale.ctype.virtuals-8.sentence-2)

[ð](#lib:ctype,do_tolower)

`charT        do_tolower(charT c) const;
const charT* do_tolower(charT* low, const charT* high) const;
`

[9](#locale.ctype.virtuals-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1581)

*Effects*: Converts a character or characters to lower case[.](#locale.ctype.virtuals-9.sentence-1)

The second form replaces
each character *p in the range [low, high)
and for which a corresponding lower-case character exists,
with that character[.](#locale.ctype.virtuals-9.sentence-2)

[10](#locale.ctype.virtuals-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1589)

*Returns*: The first form returns
the corresponding lower-case character if it is known to exist, or
its argument if not[.](#locale.ctype.virtuals-10.sentence-1)

The second form returns high[.](#locale.ctype.virtuals-10.sentence-2)

[ð](#lib:ctype,do_widen)

`charT        do_widen(char c) const;
const char*  do_widen(const char* low, const char* high, charT* dest) const;
`

[11](#locale.ctype.virtuals-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1604)

*Effects*: Applies the simplest reasonable transformation
from a char value or sequence of char values
to the corresponding charT value or values[.](#locale.ctype.virtuals-11.sentence-1)[217](#footnote-217 "The parameter c of do_­widen is intended to accept values derived from character-literals for conversion to the locale's encoding.")

The only characters for which unique transformations are required
are those in the basic character set ([[lex.charset]](lex.charset "5.3.1 Character sets"))[.](#locale.ctype.virtuals-11.sentence-2)

For any named ctype category with
a ctype<char> facet ctc and
valid ctype_base​::​mask value M,(ctc.​is(M, c) || !is(M, do_widen(c)) ) is true[.](#locale.ctype.virtuals-11.sentence-3)[218](#footnote-218 "In other words, the transformed character is not a member of any character classification that c is not also a member of.")

The second form transforms
each character *p in the range [low, high),
placing the result in dest[p - low][.](#locale.ctype.virtuals-11.sentence-4)

[12](#locale.ctype.virtuals-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1631)

*Returns*: The first form returns the transformed value[.](#locale.ctype.virtuals-12.sentence-1)

The second form returns high[.](#locale.ctype.virtuals-12.sentence-2)

[ð](#lib:ctype,do_narrow)

`char         do_narrow(charT c, char dfault) const;
const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const;
`

[13](#locale.ctype.virtuals-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1644)

*Effects*: Applies the simplest reasonable transformation
from a charT value or sequence of charT values
to the corresponding char value or values[.](#locale.ctype.virtuals-13.sentence-1)

For any character c in the basic character set ([[lex.charset]](lex.charset "5.3.1 Character sets"))
the transformation is such thatdo_widen(do_narrow(c, 0)) == c

For any named ctype category with
a ctype<char> facet ctc however, andctype_base​::​mask value M,(is(M, c) || !ctc.is(M, do_narrow(c, dfault)) ) is true (unless do_narrow returns dfault)[.](#locale.ctype.virtuals-13.sentence-3)

In addition, for any digit character c,
the expression (do_narrow(c, dfault) - '0') evaluates to the digit value of the character[.](#locale.ctype.virtuals-13.sentence-4)

The second form transforms
each character *p in the range [low, high),
placing the result
(or dfault if no simple transformation is readily available)
in dest[p - low][.](#locale.ctype.virtuals-13.sentence-5)

[14](#locale.ctype.virtuals-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1672)

*Returns*: The first form returns the transformed value;
or dfault if no mapping is readily available[.](#locale.ctype.virtuals-14.sentence-1)

The second form returns high[.](#locale.ctype.virtuals-14.sentence-2)

[217)](#footnote-217)[217)](#footnoteref-217)

The parameter c of do_widen is intended to
accept values derived from [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s* for conversion to the locale's encoding[.](#footnote-217.sentence-1)

[218)](#footnote-218)[218)](#footnoteref-218)

In other words, the transformed character is not
a member of any character classification
that c is not also a member of[.](#footnote-218.sentence-1)

#### [28.3.4.2.3](#locale.ctype.byname) Class template ctype_byname [[locale.ctype.byname]](locale.ctype.byname)

[ð](#lib:ctype_byname)

namespace std {template<class charT>class ctype_byname : public ctype<charT> {public:using mask = typename ctype<charT>::mask; explicit ctype_byname(const char*, size_t refs = 0); explicit ctype_byname(const string&, size_t refs = 0); protected:~ctype_byname(); };}

#### [28.3.4.2.4](#facet.ctype.special) ctype<char> specialization [[facet.ctype.special]](facet.ctype.special)

#### [28.3.4.2.4.1](#facet.ctype.special.general) General [[facet.ctype.special.general]](facet.ctype.special.general)

[ð](#lib:ctype%3cchar%3e)

namespace std {template<>class ctype<char> : public locale::facet, public ctype_base {public:using char_type = char; explicit ctype(const mask* tab = nullptr, bool del = false, size_t refs = 0); bool is(mask m, char c) const; const char* is(const char* low, const char* high, mask* vec) const; const char* scan_is (mask m, const char* low, const char* high) const; const char* scan_not(mask m, const char* low, const char* high) const; char toupper(char c) const; const char* toupper(char* low, const char* high) const; char tolower(char c) const; const char* tolower(char* low, const char* high) const; char widen(char c) const; const char* widen(const char* low, const char* high, char* to) const; char narrow(char c, char dfault) const; const char* narrow(const char* low, const char* high, char dfault, char* to) const; static locale::id id; static const size_t table_size = *implementation-defined*; const mask* table() const noexcept; static const mask* classic_table() noexcept; protected:~ctype(); virtual char do_toupper(char c) const; virtual const char* do_toupper(char* low, const char* high) const; virtual char do_tolower(char c) const; virtual const char* do_tolower(char* low, const char* high) const; virtual char do_widen(char c) const; virtual const char* do_widen(const char* low, const char* high, char* to) const; virtual char do_narrow(char c, char dfault) const; virtual const char* do_narrow(const char* low, const char* high, char dfault, char* to) const; };}

[1](#facet.ctype.special.general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1748)

A specialization ctype<char> is provided
so that the member functions on type char can be implemented inline[.](#facet.ctype.special.general-1.sentence-1)[219](#footnote-219 "Only the char (not unsigned char and signed char) form is provided. The specialization is specified in the standard, and not left as an implementation detail, because it affects the derivation interface for ctype<char>.")

The implementation-defined value of
member table_size is at least 256[.](#facet.ctype.special.general-1.sentence-2)

[219)](#footnote-219)[219)](#footnoteref-219)

Only the char (not unsigned char and signed char)
form is provided[.](#footnote-219.sentence-1)

The specialization is specified in the standard,
and not left as an implementation detail,
because it affects the derivation interface for ctype<char>[.](#footnote-219.sentence-2)

#### [28.3.4.2.4.2](#facet.ctype.char.dtor) Destructor [[facet.ctype.char.dtor]](facet.ctype.char.dtor)

[ð](#lib:ctype%3cchar%3e,destructor)

`~ctype();
`

[1](#facet.ctype.char.dtor-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1769)

*Effects*: If the constructor's first argument was nonzero, and
its second argument was true,
does delete [] table()[.](#facet.ctype.char.dtor-1.sentence-1)

#### [28.3.4.2.4.3](#facet.ctype.char.members) Members [[facet.ctype.char.members]](facet.ctype.char.members)

[1](#facet.ctype.char.members-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1778)

In the following member descriptions,
for unsigned char values v where v >= table_size,table()[v] is assumed to have an implementation-specific value
(possibly different for each such value v)
without performing the array lookup[.](#facet.ctype.char.members-1.sentence-1)

[ð](#lib:ctype%3cchar%3e,constructor)

`explicit ctype(const mask* tbl = nullptr, bool del = false, size_t refs = 0);
`

[2](#facet.ctype.char.members-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1792)

*Preconditions*: Either tbl == nullptr is true or
[tbl, tbl + table_size) is a valid range[.](#facet.ctype.char.members-2.sentence-1)

[3](#facet.ctype.char.members-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1797)

*Effects*: Passes its refs argument to its base class constructor[.](#facet.ctype.char.members-3.sentence-1)

[ð](#lib:ctype%3cchar%3e,is)

`bool        is(mask m, char c) const;
const char* is(const char* low, const char* high, mask* vec) const;
`

[4](#facet.ctype.char.members-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1809)

*Effects*: The second form, for all *p in the range [low, high),
assigns into vec[p - low] the value table()[(unsigned char)*p][.](#facet.ctype.char.members-4.sentence-1)

[5](#facet.ctype.char.members-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1814)

*Returns*: The first form returns table()[(unsigned char)c] & m;
the second form returns high[.](#facet.ctype.char.members-5.sentence-1)

[ð](#lib:ctype%3cchar%3e,scan_is)

`const char* scan_is(mask m, const char* low, const char* high) const;
`

[6](#facet.ctype.char.members-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1826)

*Returns*: The smallest p in the range [low, high) such thattable()[(unsigned char) *p] & m is true[.](#facet.ctype.char.members-6.sentence-1)

[ð](#lib:ctype%3cchar%3e,scan_not)

`const char* scan_not(mask m, const char* low, const char* high) const;
`

[7](#facet.ctype.char.members-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1841)

*Returns*: The smallest p in the range [low, high) such thattable()[(unsigned char) *p] & m is false[.](#facet.ctype.char.members-7.sentence-1)

[ð](#lib:ctype%3cchar%3e,toupper)

`char        toupper(char c) const;
const char* toupper(char* low, const char* high) const;
`

[8](#facet.ctype.char.members-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1857)

*Returns*: do_toupper(c) or do_toupper(low, high), respectively[.](#facet.ctype.char.members-8.sentence-1)

[ð](#lib:ctype%3cchar%3e,tolower)

`char        tolower(char c) const;
const char* tolower(char* low, const char* high) const;
`

[9](#facet.ctype.char.members-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1869)

*Returns*: do_tolower(c) or do_tolower(low, high), respectively[.](#facet.ctype.char.members-9.sentence-1)

[ð](#lib:ctype%3cchar%3e,widen)

`char  widen(char c) const;
const char* widen(const char* low, const char* high, char* to) const;
`

[10](#facet.ctype.char.members-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1881)

*Returns*: do_widen(c) ordo_widen(low, high, to), respectively[.](#facet.ctype.char.members-10.sentence-1)

[ð](#lib:ctype%3cchar%3e,narrow)

`char        narrow(char c, char dfault) const;
const char* narrow(const char* low, const char* high, char dfault, char* to) const;
`

[11](#facet.ctype.char.members-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1895)

*Returns*: do_narrow(c, dfault) ordo_narrow(low, high, dfault, to),
respectively[.](#facet.ctype.char.members-11.sentence-1)

[ð](#lib:ctype%3cchar%3e,table)

`const mask* table() const noexcept;
`

[12](#facet.ctype.char.members-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1910)

*Returns*: The first constructor argument, if it was nonzero,
otherwise classic_table()[.](#facet.ctype.char.members-12.sentence-1)

#### [28.3.4.2.4.4](#facet.ctype.char.statics) Static members [[facet.ctype.char.statics]](facet.ctype.char.statics)

[ð](#lib:ctype%3cchar%3e,classic_table)

`static const mask* classic_table() noexcept;
`

[1](#facet.ctype.char.statics-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1924)

*Returns*: A pointer to the initial element of an array of size table_size which represents the classifications of characters in the "C" locale[.](#facet.ctype.char.statics-1.sentence-1)

#### [28.3.4.2.4.5](#facet.ctype.char.virtuals) Virtual functions [[facet.ctype.char.virtuals]](facet.ctype.char.virtuals)

[ð](#lib:ctype%3cchar%3e,do_toupper)

char do_toupper(char) const;const char* do_toupper(char* low, const char* high) const;char do_tolower(char) const;const char* do_tolower(char* low, const char* high) const;

virtual char do_widen(char c) const;virtual const char* do_widen(const char* low, const char* high, char* to) const;virtual char do_narrow(char c, char dfault) const;virtual const char* do_narrow(const char* low, const char* high, char dfault, char* to) const;

[1](#facet.ctype.char.virtuals-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L1949)

These functions are described identically as those members of the same name
in the ctype class template ([[locale.ctype.members]](#locale.ctype.members "28.3.4.2.2.2 ctype members"))[.](#facet.ctype.char.virtuals-1.sentence-1)

#### [28.3.4.2.5](#locale.codecvt) Class template codecvt [[locale.codecvt]](locale.codecvt)

#### [28.3.4.2.5.1](#locale.codecvt.general) General [[locale.codecvt.general]](locale.codecvt.general)

[ð](#lib:codecvt)

namespace std {class codecvt_base {public:enum result { ok, partial, error, noconv }; }; template<class internT, class externT, class stateT>class codecvt : public locale::facet, public codecvt_base {public:using intern_type = internT; using extern_type = externT; using state_type = stateT; explicit codecvt(size_t refs = 0);

 result out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next,
 externT* to, externT* to_end, externT*& to_next) const;

 result unshift( stateT& state,
 externT* to, externT* to_end, externT*& to_next) const;

 result in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next,
 internT* to, internT* to_end, internT*& to_next) const; int encoding() const noexcept; bool always_noconv() const noexcept; int length(stateT&, const externT* from, const externT* end, size_t max) const; int max_length() const noexcept; static locale::id id; protected:~codecvt(); virtual result do_out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next,
 externT* to, externT* to_end, externT*& to_next) const; virtual result do_in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next,
 internT* to, internT* to_end, internT*& to_next) const; virtual result do_unshift( stateT& state,
 externT* to, externT* to_end, externT*& to_next) const; virtual int do_encoding() const noexcept; virtual bool do_always_noconv() const noexcept; virtual int do_length(stateT&, const externT* from, const externT* end, size_t max) const; virtual int do_max_length() const noexcept; };}

[1](#locale.codecvt.general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2017)

The class codecvt<internT, externT, stateT> is for use
when converting from one character encoding to another,
such as from wide characters to multibyte characters or
between wide character encodings such as UTF-32 and EUC[.](#locale.codecvt.general-1.sentence-1)

[2](#locale.codecvt.general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2023)

The stateT argument selects
the pair of character encodings being mapped between[.](#locale.codecvt.general-2.sentence-1)

[3](#locale.codecvt.general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2027)

The specializations required
in Table [91](locale.category#tab:locale.category.facets "Table 91: Locale category facets") ([[locale.category]](locale.category "28.3.3.1.2.1 Type locale​::​category"))
convert the implementation-defined native character set[.](#locale.codecvt.general-3.sentence-1)

codecvt<char, char, mbstate_t> implements a degenerate conversion;
it does not convert at all[.](#locale.codecvt.general-3.sentence-2)

codecvt<wchar_t, char, mbstate_t> converts between the native character sets for ordinary and wide characters[.](#locale.codecvt.general-3.sentence-3)

Specializations on mbstate_t perform conversion between encodings known to the library implementer[.](#locale.codecvt.general-3.sentence-4)

Other encodings can be converted by specializing on
a program-defined stateT type[.](#locale.codecvt.general-3.sentence-5)

Objects of type stateT can contain any state
that is useful to communicate to or from
the specialized do_in or do_out members[.](#locale.codecvt.general-3.sentence-6)

#### [28.3.4.2.5.2](#locale.codecvt.members) Members [[locale.codecvt.members]](locale.codecvt.members)

[ð](#lib:codecvt,out)

`result out(
  stateT& state,
  const internT* from, const internT* from_end, const internT*& from_next,
  externT* to, externT* to_end, externT*& to_next) const;
`

[1](#locale.codecvt.members-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2054)

*Returns*: do_out(state, from, from_end, from_next, to, to_end, to_next)[.](#locale.codecvt.members-1.sentence-1)

[ð](#lib:codecvt,unshift)

`result unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const;
`

[2](#locale.codecvt.members-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2065)

*Returns*: do_unshift(state, to, to_end, to_next)[.](#locale.codecvt.members-2.sentence-1)

[ð](#lib:codecvt,in)

`result in(
  stateT& state,
  const externT* from, const externT* from_end, const externT*& from_next,
  internT* to, internT* to_end, internT*& to_next) const;
`

[3](#locale.codecvt.members-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2079)

*Returns*: do_in(state, from, from_end, from_next, to, to_end, to_next)[.](#locale.codecvt.members-3.sentence-1)

[ð](#lib:codecvt,encoding)

`int encoding() const noexcept;
`

[4](#locale.codecvt.members-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2090)

*Returns*: do_encoding()[.](#locale.codecvt.members-4.sentence-1)

[ð](#lib:codecvt,always_noconv)

`bool always_noconv() const noexcept;
`

[5](#locale.codecvt.members-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2101)

*Returns*: do_always_noconv()[.](#locale.codecvt.members-5.sentence-1)

[ð](#lib:codecvt,length)

`int length(stateT& state, const externT* from, const externT* from_end, size_t max) const;
`

[6](#locale.codecvt.members-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2112)

*Returns*: do_length(state, from, from_end, max)[.](#locale.codecvt.members-6.sentence-1)

[ð](#lib:codecvt,max_length)

`int max_length() const noexcept;
`

[7](#locale.codecvt.members-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2123)

*Returns*: do_max_length()[.](#locale.codecvt.members-7.sentence-1)

#### [28.3.4.2.5.3](#locale.codecvt.virtuals) Virtual functions [[locale.codecvt.virtuals]](locale.codecvt.virtuals)

[ð](#lib:codecvt,do_out)

`result do_out(
  stateT& state,
  const internT* from, const internT* from_end, const internT*& from_next,
  externT* to, externT* to_end, externT*& to_next) const;

result do_in(
  stateT& state,
  const externT* from, const externT* from_end, const externT*& from_next,
  internT* to, internT* to_end, internT*& to_next) const;
`

[1](#locale.codecvt.virtuals-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2145)

*Preconditions*: (from <= from_end && to <= to_end) is well-defined and true;state is initialized, if at the beginning of a sequence,
or else is equal to the result of converting
the preceding characters in the sequence[.](#locale.codecvt.virtuals-1.sentence-1)

[2](#locale.codecvt.virtuals-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2152)

*Effects*: Translates characters in the source range [from, from_end),
placing the results in sequential positions starting at destination to[.](#locale.codecvt.virtuals-2.sentence-1)

Converts no more than (from_end - from) source elements, and
stores no more than (to_end - to) destination elements[.](#locale.codecvt.virtuals-2.sentence-2)

[3](#locale.codecvt.virtuals-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2159)

Stops if it encounters a character it cannot convert[.](#locale.codecvt.virtuals-3.sentence-1)

It always leaves the from_next and to_next pointers
pointing one beyond the last element successfully converted[.](#locale.codecvt.virtuals-3.sentence-2)

If it returns noconv,internT and externT are the same type, and
the converted sequence is identical to
the input sequence [from, from_next),to_next is set equal to to,
the value of state is unchanged, and
there are no changes to the values in [to, to_end)[.](#locale.codecvt.virtuals-3.sentence-3)

[4](#locale.codecvt.virtuals-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2171)

A codecvt facet
that is used by basic_filebuf ([[file.streams]](file.streams "31.10 File-based streams"))
shall have the property that ifdo_out(state, from, from_end, from_next, to, to_end, to_next) would return ok,
where from != from_end,
thendo_out(state, from, from + 1, from_next, to, to_end, to_next) shall also return ok,
and that ifdo_in(state, from, from_end, from_next, to, to_end, to_next) would return ok,
where to != to_end,
thendo_in(state, from, from_end, from_next, to, to + 1, to_next) shall also return ok[.](#locale.codecvt.virtuals-4.sentence-1)[220](#footnote-220 "Informally, this means that basic_­filebuf assumes that the mappings from internal to external characters is 1 to N: that a codecvt facet that is used by basic_­filebuf can translate characters one internal character at a time.")

[*Note [1](#locale.codecvt.virtuals-note-1)*:

As a result of operations on state,
it can return ok or partial and
set from_next == from and to_next != to[.](#locale.codecvt.virtuals-4.sentence-2)

â *end note*]

[5](#locale.codecvt.virtuals-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2208)

*Returns*: An enumeration value, as summarized in Table [93](#tab:locale.codecvt.inout "Table 93: do_­in/do_­out result values")[.](#locale.codecvt.virtuals-5.sentence-1)

Table [93](#tab:locale.codecvt.inout) — do_in/do_out result values [[tab:locale.codecvt.inout]](./tab:locale.codecvt.inout)  

| [ð](#tab:locale.codecvt.inout-row-1)<br>**Value** | **Meaning** |
| --- | --- |
| [ð](#tab:locale.codecvt.inout-row-2)<br>ok | completed the conversion |
| [ð](#tab:locale.codecvt.inout-row-3)<br>partial | not all source characters converted |
| [ð](#tab:locale.codecvt.inout-row-4)<br>error | encountered a character in [from, from_end) that cannot be converted |
| [ð](#tab:locale.codecvt.inout-row-5)<br>noconv | internT and externT are the same type, and input sequence is identical to converted sequence |

A return value of partial,
if (from_next == from_end),
indicates
that either the destination sequence has not absorbed
all the available destination elements, or
that additional source elements are needed
before another destination element can be produced[.](#locale.codecvt.virtuals-5.sentence-2)

[6](#locale.codecvt.virtuals-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2234)

*Remarks*: Its operations on state are unspecified[.](#locale.codecvt.virtuals-6.sentence-1)

[*Note [2](#locale.codecvt.virtuals-note-2)*:

This argument can be used, for example,
to maintain shift state,
to specify conversion options (such as count only), or
to identify a cache of seek offsets[.](#locale.codecvt.virtuals-6.sentence-2)

â *end note*]

[ð](#lib:codecvt,do_unshift)

`result do_unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const;
`

[7](#locale.codecvt.virtuals-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2251)

*Preconditions*: (to <= to_end) is well-defined and true;state is initialized, if at the beginning of a sequence,
or else is equal to the result of converting
the preceding characters in the sequence[.](#locale.codecvt.virtuals-7.sentence-1)

[8](#locale.codecvt.virtuals-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2258)

*Effects*: Places characters starting at to that should be appended to terminate a sequence
when the current stateT is given by state[.](#locale.codecvt.virtuals-8.sentence-1)[221](#footnote-221 "Typically these will be characters to return the state to stateT().")

Stores no more than (to_end - to) destination elements, and
leaves the to_next pointer
pointing one beyond the last element successfully stored[.](#locale.codecvt.virtuals-8.sentence-2)

[9](#locale.codecvt.virtuals-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2270)

*Returns*: An enumeration value, as summarized in Table [94](#tab:locale.codecvt.unshift "Table 94: do_­unshift result values")[.](#locale.codecvt.virtuals-9.sentence-1)

Table [94](#tab:locale.codecvt.unshift) — do_unshift result values [[tab:locale.codecvt.unshift]](./tab:locale.codecvt.unshift)  

| [ð](#tab:locale.codecvt.unshift-row-1)<br>**Value** | **Meaning** |
| --- | --- |
| [ð](#tab:locale.codecvt.unshift-row-2)<br>ok | completed the sequence |
| [ð](#tab:locale.codecvt.unshift-row-3)<br>partial | space for more than to_end - to destination elements was needed to terminate a sequence given the value of state |
| [ð](#tab:locale.codecvt.unshift-row-4)<br>error | an unspecified error has occurred |
| [ð](#tab:locale.codecvt.unshift-row-5)<br>noconv | no termination is needed for this state_type |

[ð](#lib:codecvt,do_encoding)

`int do_encoding() const noexcept;
`

[10](#locale.codecvt.virtuals-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2293)

*Returns*: -1 if the encoding of the externT sequence is state-dependent;
else the constant number of externT characters
needed to produce an internal character;
or 0 if this number is not a constant[.](#locale.codecvt.virtuals-10.sentence-1)[222](#footnote-222 "If encoding() yields -1, then more than max_­length() externT elements can be consumed when producing a single internT character, and additional externT elements can appear at the end of a sequence after those that yield the final internT character.")

[ð](#lib:codecvt,do_always_noconv)

`bool do_always_noconv() const noexcept;
`

[11](#locale.codecvt.virtuals-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2314)

*Returns*: true if do_in() and do_out() return noconv for all valid argument values[.](#locale.codecvt.virtuals-11.sentence-1)

codecvt<char, char, mbstate_t> returns true[.](#locale.codecvt.virtuals-11.sentence-2)

[ð](#lib:codecvt,do_length)

`int do_length(stateT& state, const externT* from, const externT* from_end, size_t max) const;
`

[12](#locale.codecvt.virtuals-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2327)

*Preconditions*: (from <= from_end) is well-defined and true;state is initialized, if at the beginning of a sequence,
or else is equal to the result of converting
the preceding characters in the sequence[.](#locale.codecvt.virtuals-12.sentence-1)

[13](#locale.codecvt.virtuals-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2334)

*Effects*: The effect on the state argument is as if
it called do_in(state, from, from_end, from, to, to + max, to) for to pointing to a buffer of at least max elements[.](#locale.codecvt.virtuals-13.sentence-1)

[14](#locale.codecvt.virtuals-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2340)

*Returns*: (from_next - from) wherefrom_next is the largest value in the range [from, from_end]
such that the sequence of values in the range [from, from_next)
representsmax or fewer valid complete characters of type internT[.](#locale.codecvt.virtuals-14.sentence-1)

The specialization codecvt<char, char, mbstate_t>,
returns the lesser of max and (from_end - from)[.](#locale.codecvt.virtuals-14.sentence-2)

[ð](#lib:codecvt,do_max_length)

`int do_max_length() const noexcept;
`

[15](#locale.codecvt.virtuals-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/text.tex#L2357)

*Returns*: The maximum value that do_length(state, from, from_end, 1) can return
for any valid range [from, from_end)
and stateT value state[.](#locale.codecvt.virtuals-15.sentence-1)

The specialization codecvt<char, char, mbstate_t>​::​do_max_length() returns 1[.](#locale.codecvt.virtuals-15.sentence-2)

[220)](#footnote-220)[220)](#footnoteref-220)

Informally, this means that basic_filebuf assumes that the mappings from internal to external characters is 1 to N:
that a codecvt facet that is used by basic_filebuf can translate characters one internal character at a time[.](#footnote-220.sentence-1)

[221)](#footnote-221)[221)](#footnoteref-221)

Typically these will be characters to return the state to stateT()[.](#footnote-221.sentence-1)

[222)](#footnote-222)[222)](#footnoteref-222)

If encoding() yields -1,
then more than max_length() externT elements
can be consumed when producing a single internT character, and
additional externT elements can appear at the end of a sequence
after those that yield the final internT character[.](#footnote-222.sentence-1)

#### [28.3.4.2.6](#locale.codecvt.byname) Class template codecvt_byname [[locale.codecvt.byname]](locale.codecvt.byname)

[ð](#lib:codecvt_byname)

namespace std {template<class internT, class externT, class stateT>class codecvt_byname : public codecvt<internT, externT, stateT> {public:explicit codecvt_byname(const char*, size_t refs = 0); explicit codecvt_byname(const string&, size_t refs = 0); protected:~codecvt_byname(); };}
