最終更新日時(UTC):
が更新

履歴 編集

char16_tとchar32_t [N2249](C++11)

このページは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_tchar32_tの入出力はサポートしない。そのため、それらの文字・文字列はシステムの文字コードに変換して入出力する必要がある。

仕様

char16_t型、char32_t型の文字・文字列リテラルと文字コード

  • char16_tchar32_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_tchar32_tはそれぞれ、<cstdint>ヘッダで定義されるuint_least16_tuint_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_tchar32_tのユニバーサルキャラクタ名は、[0x0, 0x10FFFF]の範囲内であること。

参照するUCSの規格

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にサロゲートペアはない
}

出力

UTF-32に文字コード変換して簡易的にコードポイント数を算出する

#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;
}

出力

5

この機能が必要になった背景・経緯

この機能が提案された2004年当時にはすでにUCS/Unicodeが広く普及していた。多くのユーザーがその文字コードを扱うことを望んでいたために、標準C++で正式にサポートすることとなった。

関連項目

参照