概要
C++23とは、2023年中に改訂され、ISO/IEC 14882:2024で標準規格化されたC++バージョンの通称である。
このバージョンは、策定中のためC++2bと呼ばれることがある。「(C++20である2020年の次の) 202b年にリリースされる」という伏せ字として「b」が使われているが、3年周期に次のバージョンが策定されることが決まっているため、伏せ字になっている年数がずれることはない。
言語機能
変数
| 言語機能 | 説明 |
|---|---|
(符号付き)size_tリテラルのためのサフィックス |
42z/42Zとすることでsize_tに対応する符号付き整数型のリテラルとする |
| 暗黙的なムーブを簡略化 | 参照を返す関数のreturn文で暗黙的にムーブされない問題を修正 |
これらに加えて、ライブラリ機能として拡張浮動小数点数型が定義された。<stdfloat>を参照。
関数
| 言語機能 | 説明 |
|---|---|
| スコープと名前ルックアップの仕様整理 | 複雑で不完全になっているスコープと名前ルックアップの仕様を整理し、一部の問題を解決する |
| 無意味なexport宣言を禁止する | いくつかの不必要な宣言に対するモジュールexportを禁止する |
制御構文
| 言語機能 | 説明 |
|---|---|
| 初期化文での型の別名宣言を許可 | for (using T = int; T e : v) {}を許可 |
| 範囲for文が範囲初期化子内で生じた一時オブジェクトを延命することを規定 | 範囲初期化子内で生じた一時オブジェクトは範囲for文の終わりまで延命される |
| 複合文の末尾へのラベルを許可 | C互換のため、複合文の末尾でのgoto文のラベルを許可する |
クラス
| 言語機能 | 説明 |
|---|---|
| 自身のオブジェクトを明示的にパラメータとして指定する | メンバ関数が*thisの型・オブジェクトをパラメータとしてとり、*thisオブジェクトがconst/非const、左辺値/右辺値であるかをメンバ関数内で識別できるようにする |
| アクセス制御の異なるメンバ変数のレイアウトを宣言順に規定 | アクセス制御の異なるメンバ変数のレイアウトは並び替えを許可されていたが宣言順に規定する |
| 添字演算子の多次元サポート | operator[](int x, int y, int z)のように添字演算子のオーバーロードで複数のパラメータをとることを許可 |
thisポインタをもつ必要のない演算子をstaticとして宣言できるようにする |
状態をもたないいくつかの演算子をstaticとして宣言できるようにする |
文字列
| 言語機能 | 説明 |
|---|---|
| 異なる文字エンコーディングをもつ文字列リテラルの連結を不適格とする | auto a = u8"" L"";のような異なる文字エンコーディング同士での文字列リテラルの連結を禁止する |
| エスケープシーケンスの区切り | エスケープシーケンスの範囲を明確にする構文を追加する |
| 文字・文字列リテラル中の数値・ユニバーサルキャラクタのエスケープに関する問題解決 | |
| 1ワイド文字に収まらないワイド文字リテラルを禁止する | エンコード結果としてwchar_tの大きさに収まらないワイド文字リテラルを禁止する |
| 名前付きユニバーサルキャラクタ名 | 16進数のユニバーサルキャラクタだけでなく、その文字の名前を入力できるようにする |
テンプレート
| 言語機能 | 説明 |
|---|---|
| 変数テンプレートの部分特殊化を許可 | 変数テンプレートの部分特殊化を許可するために部分特殊化の仕様を汎用化 |
| 継承コンストラクタからのクラステンプレート引数の推論 | 継承コンストラクタからもクラステンプレート引数を推論できるようにする |
定数式
| 言語機能 | 説明 |
|---|---|
if consteval |
コンパイル時の文脈かどうかで分岐させる |
定数式の文脈でのboolへの縮小変換を許可 |
if constexpr(flags & Flags::Exec)やstatic_assert(N);を許可 |
| 定数式内での非リテラル変数、静的変数・スレッドローカル変数およびgotoとラベルの存在を許可する | コンパイル時に評価されない限り、定数式内に静的変数・スレッドローカル変数およびgoto文とラベルを含むことを許可する |
| 静的な診断メッセージの文字エンコーディング | static_assertや[[deprecated]]などの診断メッセージの文字集合に関する要件をなくす |
constexpr関数が定数実行できない場合でも適格とする |
定数式実行できない関数であっても、実際にコンパイル時に評価されない限りconstexpr指定することを許可する |
constexpr関数内でのstatic constexpr変数を許可 |
constexpr関数のローカルで定数を定義できるようにする |
constexpr関数内でconsteval関数を呼び出せない問題を軽減 |
consteval呼び出しを含むconstexpr関数を条件付きでconsteval関数とみなすようにする |
ラムダ式
| 言語機能 | 説明 |
|---|---|
ラムダ式で()を省略できる条件を緩和 |
修飾や戻り値型をともなってもパラメータリストが空であれば()を省略できる |
| ラムダ式に対する属性 | ラムダ式のいくつかの箇所に属性を記述できるようにする |
属性
| 言語機能 | 説明 |
|---|---|
| コード内容の仮定をコンパイラに伝えるassume属性 | 最適化のために、コードの仮定をコンパイラに伝える属性を標準化する |
プリプロセッサ
| 言語機能 | 説明 |
|---|---|
| 文字リテラルエンコーディングを一貫させる | プリプロセッサの条件式での文字リテラルの扱いをC++式と同様にする |
elif/elifdef/elifndefのサポートを追加 |
#if/#ifdef/#ifndefに対応する複数条件命令のサポートを追加する |
#warningのサポートを追加 |
多くのC++コンパイラが実装していたプリプロセス時の警告#warning messageを正式サポート |
| 汎用的なソースコードのエンコーディングとしてUTF-8をサポート | すべてのコンパイラはUTF-8文字コードのソースコードをサポートしなければならない |
小さな変更
| 言語機能 | 説明 |
|---|---|
| 更新された定義済みマクロ | 標準規格で定義されたマクロの更新 |
| 参照するPOSIX規格を更新 | 新しいPOSIX規格の機能を標準C++が参照していたため、参照するPOSIX規格のバージョンを更新 |
| 行末スペースを無視するよう規定 | 行末が「\ 」でおわっていた場合にMSVCは行の継続をしない実装になっていたため動作を共通化するため仕様を規定 |
ライブラリ更新の概要
新ライブラリ
- C++標準ライブラリ全体のモジュールとして
std、C互換ライブラリ全体のモジュールとしてstd.compatを追加 - スタックトレースを取得するためのライブラリとして
<stacktrace>を追加 - CとC++の間でのアトミック操作の相互運用のため、C互換ライブラリとして
<stdatomic.h>を追加 - 外部から提供されるメモリバッファでストリーム処理を行うライブラリとして
<spanstream>を追加 - 正常値とエラー値のどちらかを持つクラスおよびライブラリとして
<expected>を追加 - 多次元配列ビューのライブラリとして
<mdspan>を追加 - ノードベースではないソート済みキーによる順序付き連想コンテナのライブラリとして、
<flat_map>と<flat_set>を追加 - 書式指定で出力するライブラリとして
<print>を追加 - コルーチンによるRangeの生成をサポートする
<generator>を追加 - 拡張浮動小数点数のライブラリとして
<stdfloat>を追加
コンテナ
std::stackとstd::queueに、イテレータのペアをとるコンストラクタを追加auto v = std::vector(v, alloc);のようなアロケータ引数をともなう場合のクラステンプレートのテンプレート引数推論が動作しなかったため、各コンテナクラスのコンストラクタにおけるアロケータパラメータの型をconst Allocator&からconst std::type_identity_t<Allocator>&に修正- N要素のメモリアロケート時にアロケータが実際にどれくらいのメモリを確保したかを得られるインタフェースとして、
std::allocatorクラスに、allocate_at_least()メンバ関数を追加std::allocator_traitsクラスに、allocate_at_least()関数を追加
std::pairの転送コンストラクタにデフォルトテンプレート引数を追加することで、{}のような型推論ができない引数を渡した場合でも完全転送が行われるよう修正- 順序付き連想コンテナの要素削除の処理について、一時オブジェクトのコストを抑える拡張が行われた
<ranges>に、複数の範囲を綴じ合わせるstd::views::zipを追加<ranges>に、複数の範囲の直積をとるstd::views::cartesian_productを追加- Rangeから任意のコンテナに変換するRangeアダプタ
std::ranges::to()を追加 - Rangeから任意のコンテナに変換するために、可変長のコンテナ (
std::array以外) に、以下の機能を追加:- Rangeから変換するコンストラクタ
- Rangeを挿入する
insert_range()メンバ関数 - Rangeを先頭に追加する
prepend_range()メンバ関数 - Rangeを末尾に追加する
append_range()メンバ関数 - Rangeを代入する
assign_range()メンバ関数
- ユーザー定義のRangeアダプタがパイプライン演算子
|をサポートしやすくするために、<ranges>にstd::ranges::range_adaptor_closureクラスを追加 <ranges>に、Rangeを連結させるjoin_withを追加- Rangeを指定の大きさで分割する
std::views::chunkと、Rangeを指定の大きさの隣接要素で分割するstd::views::slideを追加 - Rangeを条件一致する間の要素で分割する
std::views::chunk_byを追加 <ranges>に、Rangeを等間隔からなるRangeに変換するstd::views::strideを追加<ranges>に、Rangeをムーブするためのstd::views::as_rvalueを追加<ranges>に、指定した値をN回繰り返すRangeを生成するstd::views::repeatを追加<ranges>に、Rangeをインデックス付きでループさせるstd::views::enumerateを追加
アルゴリズム
<algorithm>に、範囲の先頭が指定した範囲と合致するかを判定するstd::ranges::starts_with()、範囲の末尾が指定した範囲と合致するかを判定するstd::ranges::ends_with()を追加<algorithm>に、要素を左シフトさせるRangeアルゴリズムstd::ranges::shift_left()、要素を右シフトさせるRangeアルゴリズムstd::ranges::shift_right()を追加<algorithm>に、範囲の末尾から要素を検索する以下のアルゴリズムを追加:<algorithm>に、範囲に特定の値が含まれているかを判定するstd::ranges::contains()、std::ranges::contains_subrangeを追加<algorithm>に、数値に限定しない汎用的な畳み込みアルゴリズムとして、以下を追加:<numeric>に、連番を生成するRangeアルゴリズムstd::ranges::iota()を追加
文字列
std::basic_stringクラスとstd::basic_string_viewクラスに、文字列内に指定した文字・文字列が含まれているかを判定するメンバ関数contains()を追加std::basic_string_viewのコンストラクタに、範囲をとるオーバーロードを追加std::string s = nullptr;のような文字列オブジェクトにnullptrを代入するようなコードはバグの元であるため、std::basic_stringとstd::basic_string_viewに、nullptr_tをとるコンストラクタをdelete定義として追加std::basic_stringクラスに、resize時に任意の初期化を行うresize_and_overwrite()メンバ関数を追加std::basic_stringクラスのコンストラクタとsubstr()メンバ関数に一時オブジェクトのオーバーロードを追加std::format()関数でRange・コンテナ、std::tuple、std::pairを出力できるよう、std::formatterに特殊化を追加- Range・シーケンスコンテナは
[1, 2, 3]、["hello", "world"]、['a', 'b', 'c']のように出力される - 連想コンテナの場合、
std::map<int, int>{{1, 2}, {3, 4}}は{1: 2, 3: 4}のように出力され、std::set<int>{1, 2, 3}は{1, 2, 3}のように出力される std::tuple、std::pairは(1, 2)のように出力される
- Range・シーケンスコンテナは
std::format()関数のフォーマット指定子としてデバッグ指定「"?"」を追加。これは文字・文字列を引用符で囲み、エスケープシーケンスをエスケープする- ただし、Range・コンテナ中の文字・文字列はデフォルトでエスケープされる
format("{:?}", "h\tello")は"h\tello"のように出力される
入出力
std::basic_ostreamクラスのoperator<<に、const volatile void*をとるオーバーロードを追加- ファイルを開く際のオプションとして、排他モードを表す
noreplaceを追加
関数オブジェクト
std::invoke()の戻り値型を指定するバージョンであるstd::invoke_r()を追加std::functionクラスと等価な機能をもつ、ムーブのみ可能なstd::move_only_functionクラスを追加- ユーザー定義のRangeアダプタがパイプライン演算子
|をサポートしやすくするために、末尾から引数を束縛するstd::bind_back()関数を追加
メモリ
<memory>に、レガシーC関数からスマートポインタへの直接出力をサポートする、スマートポインタアダプタstd::out_ptrとstd::inout_ptrを追加std::unique_ptrクラスをconstexprに対応<memory>に、オブジェクトの生存期間を開始することを明示する関数として、std::start_lifetime_as()とstd::start_lifetime_as_array()を追加<bit>に、値のバイト入れ替え (エンディアン変換) を行うstd::byteswap()関数を追加
ユーティリティ
std::visit()に指定できるバリアントオブジェクトを、直接的な「std::variant型の特殊化であること」という制約を緩和し、std::variantから派生した型も許可<utility>に、列挙値を基底型に変換するstd::to_underlying()関数を追加<utility>に、 (主に) メンバ変数を転送するため、指定された型のconst性と参照修飾で引数を転送するstd::forward_like()関数を追加std::optionalクラスにモナド操作としてメンバ関数and_then()、transform()、or_else()を追加- 到達しないパスであることを表明する関数
std::unreachable()を追加 std::bitsetクラスをさらにconstexpr対応
型情報
std::type_infoクラスのoperator==をconstexprに対応
型特性
<type_traits>に、スコープ付き列挙型かを判定する型特性std::is_scoped_enumを追加<type_traits>に、一時オブジェクトの参照への束縛を検出するための型特性として、以下を追加:<type_traits>に、暗黙的に構築される型かを判定する型特性std::is_implicit_lifetimeを追加
C互換ライブラリ
機能の非推奨化
std::aligned_storageとstd::aligned_unionを非推奨化。これらの機能は未定義動作を引き起こし、間違った保証が行われ、よくないAPI設計が行われていたため、非推奨とするstd::aligned_storageの代わりにalignas(T) std::byte[sizeof(T)];を使用することを推奨するstd::aligned_unionの代わりにalignas(Ts...) std::byte[std::max({sizeof(Ts)...})];を使用することを推奨する
std::allocatorのメンバ型is_always_equalを非推奨化。これはアロケータが状態をもたないことを表す型でありデフォルトではtrue_typeとなっている。状態をもつユーザー定義のアロケータ型でこのメンバ型の上書きを忘れることでバグが埋め込まれてしまっていたため誤用防止のために非推奨とする<limits>の以下の非正規化数に関する機能を非推奨化。これらの機能は必ずしもコンパイル時に決まらない可能性のある値であり有用でないため、非推奨とする
機能の削除
- ガベージコレクションの実装にうまく役立てられなかった、ガベージコレクション実装のサポートをする以下の機能を削除する:
取り決め
- 以下のヘッダの一部機能をフリースタンディングライブラリとして追加: