- cpp11[meta cpp]
このページはC++11に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
char16_t
はUTF-16符号化形式の文字型、char32_t
はUTF-32符号化形式の文字型である。
UTF-16とUTF-32は、ISO/IEC 10646で標準化されている文字コード「UCS (Universal Coded Character Set)」とその互換文字コードである「Unicode (ユニコード)」で定義されている符号化形式である。UTF-16は、ひとつのコードポイント(≒文字)を表すために16ビットを基本的に使用する。UTF-32は32ビットである。
標準C++では、これらの文字符号化形式を表す文字型、そのリテラル、および文字コード・符号化形式を変換する機能を提供する。
// UTF-16/UTF-32符号化形式の文字列。
// uプレフィックスを付けた文字列リテラルはchar16_tのシーケンスとなる。
// Uプレフィックスを付けた文字列リテラルはchar32_tのシーケンスとなる。
char16_t s16[] = u"あいうえお";
char32_t s32[] = U"あいうえお";
// 文字列中にユニバーサルキャラクタ名を直接入力できる。
// \uからはじめて4桁、もしくは\Uからはじめて8桁がユニバーサルキャラクタ名として扱われる。
char16_t s[] = u"\U00020BB7野家"; // 𠮷野家
ただし、C++11時点で、標準ライブラリではchar16_t
とchar32_t
の入出力はサポートしない。そのため、それらの文字・文字列はシステムの文字コードに変換して入出力する必要がある。
char16_t
とchar32_t
は予約語(キーワード)である。u
プレフィックスが付く文字リテラルの型はchar16_t
であり、u
プレフィックスが付く文字列リテラルの要素型はchar16_t
である。- ひとつの文字を含む
char16_t
リテラルの値は、ひとつの16ビットコードポイントで表現できるISO 10646のコードポイント値と同じである。 - ひとつの値を16ビットで表現できない場合、プログラムは不適格となる。
- 複数の文字を含む
char16_t
文字リテラルは不適格である。 char16_t
文字リテラルが、基本文字集合とユニバーサルキャラクタ名より多くを含む場合は実装定義となる。char16_t
の場合、ひとつの文字がひとつ以上のchar16_t
を生成することがある。その文字はサロゲートペアと呼ばれる。char16_t
型の文字列リテラルは、静的ストレージに配置される。
- ひとつの文字を含む
U
プレフィックスが付く文字リテラルの型はchar32_t
であり、U
プレフィックスが付く文字列リテラルの要素型はchar32_t
である。- ひとつの文字を含む
char32_t
リテラルの値は、ひとつの32ビットコードポイントで表現できるISO 10646のコードポイント値と同じである。 - ひとつの値を32ビットで表現できない場合、プログラムは不適格となる。
- 複数の文字を含む
char32_t
文字リテラルは不適格である。 char32_t
文字リテラルが、基本文字集合とユニバーサルキャラクタ名より多くを含む場合は実装定義となる。char32_t
型の文字列リテラルは、静的ストレージに配置される。
- ひとつの文字を含む
char16_t
とchar32_t
はそれぞれ、<cstdint>
ヘッダで定義されるuint_least16_t
とuint_least32_t
と、サイズ、符号の有無、アライメントが同じである。<cuchar>
ヘッダでマクロ__STDC_UTF_16__
が定義される場合、char16_t
型の値はUTF-16の妥当なコードポイントを持つ。そうでない場合、char16_t
型の値は実装定義の文字コードとなる。<cuchar>
ヘッダでマクロ__STDC_UTF_32__
が定義される場合、char32_t
型の値はUTF-32の妥当なコードポイントを持つ。そうでない場合、char32_t
型の値は実装定義の文字コードとなる。
-
char16_t
文字・文字列リテラルとchar32_t
文字・文字列リテラルのなかには、UCS/Unicodeのユニバーサルキャラクタ名を直接記述できる。たとえば、char16_t
文字リテラルu'\u215A'
はU+215Aコードポイントの文字である'⅚'
(VULGAR FRACTION FIVE SIXTHS) を表す。\u
の場合は16進数で4桁固定のユニバーサルキャラクタ名を、\U
の場合は16進数で8桁固定のユニバーサルキャラクタ名を記述する。#include <cassert> int main() { char16_t a = u'\u215A'; char16_t b = u'⅚'; assert(a == b); }
-
char16_t
とchar32_t
のユニバーサルキャラクタ名は、[0x0, 0x10FFFF]
の範囲内であること。
C++11時点の規格では、UCSの規格としてISO/IEC 10646-1:1993を参照する。
#include <cassert>
#include <string>
int main()
{
std::u16string s16 = u"𠮷野家";
std::u32string s32 = U"𠮷野家";
assert(s16.size() == 4); // サロゲートペアを含むので1文字分多い
assert(s32.size() == 3); // UTF-32にサロゲートペアはない
}
- size()[link /reference/string/basic_string/size.md]
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
int main()
{
// UTF-8とUTF-32の相互変換を行うコンバーター
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
// UTF-8からUTF-32に変換
std::string u8str = u8"あいうえお";
std::u32string u32str = converter.from_bytes(u8str);
// コードポイント数を取得
std::size_t codepoint_count = u32str.size();
std::cout << codepoint_count << std::endl;
}
- std::wstring_convert[link /reference/locale/wstring_convert.md]
- std::codecvt_utf8[link /reference/codecvt/codecvt_utf8.md]
- from_bytes[link /reference/locale/wstring_convert/from_bytes.md]
- size()[link /reference/string/basic_string/size.md]
5
この機能が提案された2004年当時にはすでにUCS/Unicodeが広く普及していた。多くのユーザーがその文字コードを扱うことを望んでいたために、標準C++で正式にサポートすることとなった。
u16string
u32string
wstring_convert
- C++11 UTF-8文字列リテラル
- C++20 UTF-8エンコーディングされた文字の型として
char8_t
を追加 - C++20
char16_t
とchar32_t
の文字・文字列リテラルを、文字コードUTF-16/32に規定 - ostream
operator<<
- C++23 名前付きユニバーサルキャラクタ名
- C++23 エスケープシーケンスの区切り
- WG14 N1040 Extensions for the programming language C to support new character data types
- N1628 Extensions for the Programming Language C++ to Support New Character Data Types
- N1823 New Character Types in C++
- N1955 New Character Types in C++
- N2018 New Character Types in C++
- N2149 New Character Types in C++
- N2249 New Character Types in C++
- N2170 Universal Character Names in Literals