[C++]WG21月次提案文書を眺める(2025年04月)

文書の一覧

全部で34本あります。

もくじ

P0260R17 C++ Concurrent Queues

標準ライブラリに並行キューを追加するための設計を練る提案。

以前の記事を参照

このリビジョンでの変更は

  • 待機中の処理のブロック解除を明示する文言を追加
  • busy_asyncの説明を充実

などです。

P1789R1 Library Support for Expansion Statements

std::integer_sequenceを構造化束縛および展開ステートメントで使用できるようにする提案。

構造化束縛でのパック展開(P1061R10)と展開ステートメント(P1306R3)はどちらもC++26で導入される新機能です。これらの機能では、畳み込み式やforループのような機構を利用して構造化束縛可能な型をコンパイル時にイテレーションすることができます。

しかし、これらの新しい機能で使用可能なコンパイル時整数シーケンスを得る簡易な方法は提供されていません。現在はそのような用途のためにラムダ式とその呼び出し時の型推論を利用して所望の長さの整数パックを得るパターンが良く使用されます。

[]<std::size_t ...INDEX>(std::index_sequence<INDEX...>) {
  // 整数パックを使用する処理をここに記述する... 
} (std::make_index_sequence<COUNT>());

これは、回りくどい構文に加えて関数内に余計なネストを導入してしまうという微妙さもあります。リフレクションの導入に伴ってメタプログラミングが活発になり、このようなパターンの使用機会が増加することを考えると、このようなパターンをより使いやすくする必要があります。

この提案ではそのために、std::integer_sequenceを構造化束縛可能にすることを提案しています。これによって、整数シーケンスのパックを簡単に得ることができるようになり、またそれによるループを簡単に記述できるようになります。

// 構造化束縛によるパック導入
constexpr auto [...INDEX] = std::make_index_sequence<COUNT>();
// 整数パック`INDEX`を直接使用できる
...
// 展開ステートメントによる整数パックのイテレーション
template for (constexpr size_t INDEX : std::make_index_sequence<COUNT>()) {
  ...
}

std::integer_sequenceを構造化束縛対応させる方法として、ここではタプルプロトコルを実装する方法を提案しています。

提案文書より、サンプル実装

template<class T, T ...VALUES>
struct tuple_size<integer_sequence<T, VALUES...>>
  : integral_constant<size_t, sizeof...(VALUES)>
{};

template<size_t INDEX, class T, T ...VALUES>
  requires (INDEX < sizeof...(VALUES))
struct tuple_element<INDEX, integer_sequence<T, VALUES...>> {
  using type = T;
};

template<size_t INDEX, class T, T ...VALUES>
  requires (INDEX < sizeof...(VALUES))
constexpr T get(integer_sequence<T, VALUES...>) noexcept {
  return VALUES...[INDEX];
}

タプルの比較演算子実装のサンプルコード

// ラムダによる実装
template<class...TTypes, class...UTypes>
  requires(sizeof...(TTypes) == sizeof...(UTypes))
constexpr bool operator==(tuple<TTypes...> const &lhs, tuple<UTypes...> const& rhs) {
  return [&, this]<size_t ...INDEX>(index_sequence<INDEX...>){
    return ((get<INDEX>(lhs) == get<INDEX>(rhs)) && ...);
  }(index_sequence_for<TTypes...>());
}

// この提案による畳み込み式での実装
template<class...TTypes, class...UTypes>
  requires(sizeof...(TTypes) == sizeof...(UTypes))
constexpr bool operator==(tuple<TTypes...> const &lhs, tuple<UTypes...> const& rhs) {
  constexpr auto [...INDEX] = index_sequence_for<TTypes...>{};

  return ((get<INDEX>(lhs) == get<INDEX>(rhs)) && ...);
}

関数引数リフレクション(P3096R5)による引数の転送の記述サンプル

// ラムダによる実装(間違い
void foo(int x, char c) {
  [:expand(parameters_of(^^foo)):]
  >> []<auto ...parameters>(){
    bar([:parameters:]...); // oops
  }
}

// この提案による構造化束縛でのパック導入による実装
void foo(int x, char c) {
  constexpr auto [...INDEX] = std::make_index_sequence<parameters_of(^^foo).size()>();
  bar([:parameters_of(^^foo)[INDEX]:]...);
}

このexpandはP2996R7で使用されているtemplate forの代わりとなる機能です。関数引数リフレクションは取得した関数内部でのみスプライスすることができますが、ラムダによって関数スコープを導入するとこれが問題になります。template forはこの問題を軽減するものの、畳み込み式を使用したり(下の例のように)引数リストとして展開したい場合に使用できません。

P2019R8 Thread attributes

std::thread/std::jthreadにおいて、そのスレッドのスタックサイズとスレッド名を実行開始前に設定できるようにする提案。

以前の記事を参照

このリビジョンでの変更は

などです。

P2902R1 constexpr 'Parallel' Algorithms

並列アルゴリズムを定数式で使用できるようにする提案。

以前の記事を参照

このリビジョンでの変更は

  • モチベーションを大きく拡張
    • C++26以降のconstexpr対応機能のリスト
    • 賛成と反対のケースについてより詳細な分析を提示
  • コンパイル時のアクセラレーションの可能性の影響について議論を追加
  • 最新のWDにリベース

などです。

P2988R12 std::optional<T&>

std::optionalが参照を保持することができるようにする提案。

以前の記事を参照

このリビジョンでの変更は、LWGレビューに基づく文言の修正です。

この提案は、2025年2月の全体会議でC++26に向けて採択されました。

P2996R11 Reflection for C++26

値ベースの静的リフレクションの提案。

以前の記事を参照

このリビジョンでの変更は

  • has_complete_definition()をより限定的なis_enumerable_type()に置換
  • コア言語の文言の変更
  • ライブラリの文言変更

などです。

P3037R5 constexpr std::shared_ptr and friends

std::shared_ptrを定数式でも使えるようにする提案。

以前の記事を参照

このリビジョンでの変更は

  • 提案タイトルの変更
  • std::shared_ptr/std::weak_ptrに対するstd::atomic部分特殊化のサポートを追加
  • 文言の一部の詳細な文脈を追加

などです。

P3096R8 Function Parameter Reflection in Reflection for C++26

C++26に向けた静的リフレクションに対して、関数仮引数に対するリフレクションを追加する提案。

以前の記事を参照

このリビジョンでの変更は、P2996R11と文言をそろえたことなどです。

P3126R3 Graph Library: Overview

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案の概要をまとめた文書。

以前の記事を参照

このリビジョンでの変更は

  • リファレンス実装の名前空間std::graphからgraphへ変更
  • より汎用性の高いBFS/DFSのサポート状況を更新
  • Overviewセクションに、グラフライブラリ導入の動機を追加
  • "Six Degrees of Kevin Bacon example"を拡張し、出力と追加の説明を追加
  • この提案では、スタック/キュー及び多くのアルゴリズムで発生する可能性のあるbad_alloc例外への対応の必要性があるため、スタンドアロンのグラフライブラリをサポートできないことを注記
  • "Open Design Issues"と"Open Reported Issues"セクションを更新し、提案の現在の状況を反映
    • boost::graph-likeのdescriptorの導入と、BFS/DFS及びトポロジカルソートアルゴリズムの改善などが変更点

などです。

P3127R1 Graph Library: Background and Terminology

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案の背景や動機をまとめた文書。

以前の記事を参照

このリビジョンでの変更は

  • P3126のMotivationセクションのテキストをOverviewセクションに移動
  • P3126の"Six Degrees of Kevin Bacon example"の例と重複していたのでこちらからは削除
  • C++コード例を追加して、"Direct Representation"を更新
    • 自己ループ、マルチグラフ、サイクル、ツリーなど、グラフで発生する特殊な状況についての内容を追加
  • "Incident Matrices"、"Regarding Algorithms"のセクションを追加

などです。

P3128R3 Graph Library: Algorithms

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案のうち、提案するグラフアルゴリズムについてまとめた文書。

このリビジョンでの変更は

などです。

P3129R1 Graph Library: Views

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案のうち、提案するビューについてまとめた文書。

以前の記事を参照

このリビジョンでの変更は

  • 隣接リストのピアとして、抽象データ構造としてエッジリストを追加
    • edgelist_viewによって返される範囲はbasic_sourced_index_edgelistコンセプトに準拠し、evf(uv)関数が渡された場合はhas_edge_valueコンセプトに準拠する
    • これは、BFS、DFS及びトポロジカルソートビューのすべてのSourcedバージョンに適用される
  • BFS、DFS及びトポロジカルソートビューのアロケータ引数を復元
  • この提案では、スタック/キュー及び多くのアルゴリズムで発生する可能性のあるbad_alloc例外への対応の必要性によって、スタンドアロンのグラフライブラリをサポートできないことを注記
  • 新しいBGL風のdescriptorに対応するために、descriptor構造体をinfo構造体に改名

などです。

P3130R3 Graph Library: Graph Container Interface

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案のうち、グラフの実体となるコンテナのインターフェースについてまとめた文書。

以前の記事を参照

このリビジョンでの変更は

  • boost::graph-likeのdescriptorの導入に関する変更
    • グラフコンテナで定義される具体的な頂点型と辺型は、抽象的な頂点型と辺型のdescriptorに置き換えられた
    • descriptorは、以前のバージョンのインターフェースのidとreference引数の組み合わせを置き換えた
      • これにより、vertex_id-onlyコンセプトからbasic名前修飾を持つものが削除され、数が削減された
      • P3129のビューを統合することも可能になり、basicビューも不要になったため、ビューの数も削減された
    • P3129のビューの以前のdescriptor構造体は名前の衝突を回避するためにinfo構造体に改名
      • referenceがdescriptorに置き換えられ、descriptorがコピー可能になったため、info構造体のコピー可能な型エイリアスは不要になった

などです。

P3131R3 Graph Library: Graph Containers

グラフアルゴリズムとデータ構造のためのライブラリ機能の提案のうち、グラフの実体となるコンテナ実体についてまとめた文書。

以前の記事を参照

このリビジョンでの変更は

  • P3130R3で導入されたboost::graph-likeのdescriptorに関する変更
    • descriptor構造体は名前の衝突を回避するためにinfo構造体に改名
    • descriptorは常にコピー可能であるため、compressed_graphの制約からcopyable_vertexcopyable_edgeを削除

などです。

P3161R4 Unified integer overflow arithmetic

オーバーフローを処理可能な整数演算の提案。

以前の記事を参照

このリビジョンでの変更は

  • 機能テストマクロの置換を削除
  • 最新のドラフトにリベース
  • 文言の修正

などです。

P3295R3 Freestanding constexpr containers and constexpr exception types

フリースタンディング環境の定数式において、std::vector等を使用可能にする提案。

以前の記事を参照

このリビジョンでの変更は

  • vector/stringのすべてをfreestanding-constevalにする
  • <exceptions><stdexcept>に関してはすでに標準に含まれているためここからは削除
  • <memory>string_viewの機能テストマクロを更新

などです。

P3312R1 Overload Set Types

関数のオーバーロード集合型を導入する提案。

以前の記事を参照

このリビジョンでの変更は

  • 以前のリビジョンでは関数名をバッククォートで囲むことで、「可視なオーバーロードセットが1つしかない場合でもオーバーロード集合型を作成する」と「バッククォート内の演算子シンボルを使用して、メンバスコープと名前空間スコープの両方の演算子を含むオーバーロード集合を作成できるようにする」という2つの機能が提案されていた
    • このリビジョンでは、前者の機能は将来の検討とし、後者の機能は削除
  • P0119R2とP0382R0におけるその反論を説明するセクションを追加

などです。

この提案はEWGのレビューで更なる作業をする合意が得られず、リジェクトされています。

P3348R3 C++26 should refer to C23 not C17

Cへの参照をC17からC23へ更新する提案。

以前の記事を参照

このリビジョンでの変更は

  • nextup, nextdownとその関連関数を追加
  • bsearchの正しいconstオーバーロードを追加
  • memalignmentをフリースタンディング指定
  • subclauseの番号付けを修正
  • __STDC_VERSION_xxx_H__機能テストマクロのサブセットを追加
  • va_startの文言を追加

などです。

P3371R4 Fix C++26 by making the rank-1, rank-2, rank-k, and rank-2k updates consistent with the BLAS

<linalg>の一部の関数を対応するBLAS関数の仕様と整合させる提案。

以前の記事を参照

このリビジョンでの変更は

  • 文言の差分を簡潔にするために書式を改善
  • “Implementation status”セクションを更新
  • LWG4137を前提とするようにリベース
    • これが提案にどのような影響を与えるかの説明を追加

などです。

現在のリビジョンでは次の4つの事を提案しています

  1. rank-1, rank-2, rank-k, rank-2k update系関数に、更新オーバーロードを追加
  2. 現在のrank-1, rank-2, rank-k, rank-2k update系関数の動作を、無条件更新から上書きに変更
  3. hermitian_rank_1_update(), hermitian_rank_k_update()においては、Scalarテンプレートパラメータを非複素数になるように制限する
    • これにより、このupdate動作がエルミートになることが数学的に保証される
    • この変更はLWG4136の修正と整合している
  4. rank-1, rank-k update系関数、および対称・エルミート系update関数のオーバーロードのうち、Scalar alpha引数を持たないものを削除
    • Scalar alpha引数を持つもののみが残される
    • これらのオーバーロードが後日追加されることを考慮して、線形代数数値型(linear algebra value type)がmdspanでも実行ポリシー型でもないことを制約
      • 線形代数数値型とはスカラ型および、行列・ベクトル型の単一の要素を表現する型のことで、単純には整数型や浮動小数点数型のこと

このうち2~4は破壊的変更となります。

この提案はLEWGのレビューにおいて

P3388R2 When Do You Know connect Doesn't Throw?

execution::connectによる操作が例外を送出するかどうかを早期に判定できるようにする提案。

以前の記事を参照

このリビジョンでの変更は

  • typoの修正
  • LEWGのフィードバックによる文言の更新

などです。

P3391R1 constexpr std::format

std::format()constexpr化する提案。

以前の記事を参照

このリビジョンでの変更は

  • ロケール指定Lオプションを使用すると定数式で使用できないことを明確化
  • 機能テストマクロを追加

などです。

P3395R3 Fix encoding issues and add a formatter for std::error_code

std::error_codeをフォーマット可能にする提案。

以前の記事を参照

このリビジョンでの変更は、P2930への参照を追加しこの提案との違いの説明を追加したことです。

P3481R3 std::execution::bulk() issues

std::execution::bulk()の改善提案。

以前の記事を参照

このリビジョンでの変更は、文言の改善のみです。

P3514R0 "RFC 3514: The Security Flag" for C++

RFC 3514に倣ったジョーク提案。

これはエイプリルフールネタです。

P3561R2 Index based coproduct operations on variant, and library wording

std::variantに対してインデックスに基づくvisit()操作を追加する提案。

以前の記事を参照

このリビジョンでの変更は

  • valueless_by_exception() == trueの時のセマンティクスを記述
  • 圏論的な意味論についての記述中のインデックスに関する修正
  • 未解決事項のリストを追加

などです。

P3652R1 Constexpr floating-point functions

std::to_chars/std::from_chars浮動小数点数オーバーロードconstexpr指定する提案。

以前の記事を参照

このリビジョンでの変更は

  • P3391R0(constexpr std::format)をモチベーションに追加
  • 実装経験に{fmt}musl_from_charsを追加

などです。

P3656R1 Initial draft proposal for core language UB white paper: Process and major work items

コア言語のUBに対策するための言語機能に関するホワイトペーパーのための作業や手順についての提案。

以前の記事を参照

このリビジョンでの変更は

  • 対象にはIFNDRも含まれる
  • EWGはgithubのPRではなく公開された提案文書をレビューする
  • UBに対処するための初期オプションは網羅的なものではなく、非決定性ルールのようなものは提案が必要

などです。

P3665R0 Vertical Text Processing

C++で縦書きコードをサポートする提案。

これはエイプリルフールネタです。

P3667R0 Extending range-for loop with an expression statement

範囲forで通常のforと同じような更新処理を記述できるようにする提案。

C++20で範囲forに初期化を書けるようになったことで、範囲forイテレーションしながらインデックスを使用するようなコードを書きやすくなりました。

std::array arr {2, 4, 6};

for (int i = 0; auto x : arr) {
  std::println("v[{}] = {}", i, x);
  ++i;
}

このように、範囲forの内部で使用する変数の初期化がforの外で行われなくなり、丁度良いスコープで変数を管理できるようになりました。しかし、そのような変数の更新処理はforの中で手動で管理する必要があります。コードを拡張しているうちに誤って更新処理を削除してしまったり、忘れてしまうことが起こりえます。

この提案は、範囲forにループごとの変数の更新処理を記述できるようにすることで、そのような問題を防止しようとしています。

// これを
for (int i = 0; auto x : e) {
  f(x, i);
  ++i;
}

// こう書けるようにする
for (int i = 0; auto x : e; ++i) {
  f(x, i);
}

このように、この提案後の範囲forはかなり通常のforに近い形になり、より規則的になるため教えやすさが向上します。

サンプルコードのように単純にインデックスが欲しい場合は、C++23以降std::views::enumerateを使用できます。

std::array v{2.5, 3.0, 4.5, 5.0, 5.5};

for (auto [i, x] : std::views::enumerate(v)) {
  std::println("v[{}] = {}", i, x);
}

ただし、この方法にはいくつか欠点があります。

  1. インデックスの型を指定できない
  2. 初期値を変更できない(0固定)

また、この提案のソリューションは整数インデックスの更新に限定されておらず、通常のfor同様に任意の式を更新処理として記述できるため、より汎用的になります。

P3668R0 Defaulting Postfix Increment and Decrement Operations

後置インクリメント/デクリメント演算子default定義できるようにする提案。

前置ではなく後置のインクリメント/デクリメント演算子には、多くの場合に共通するデフォルトの実装があります。それは、*thisのコピーと前置インクリメント演算子を用いた次のような実装です。

struct C {

  // 前置インクリメント演算子
  C& operator++() {
    ...
  }

  // 後置インクリメント演算子
  C operator++(int) {
    auto copy{*this};
    ++*this;
    return copy;
  }
};

イテレータの定義や整数ラッパなどのインクリメント演算子の定義時にはこのような典型的な実装を取ることがほとんどで、おおむね同じ実装になります。この提案は、この実装をデフォルト動作として、後置インクリメント/デクリメント演算子default実装を可能にするものです。

struct C {

  // 前置インクリメント演算子
  C& operator++() {
    ...
  }

  // 後置インクリメント演算子
  C operator++(int) = default;  // この提案
};

これにより、典型的な実装によるボイラープレートコードを削減でき、それによって手書き時のユーザーエラーや必要テスト数の削減などが見込まれます。また、標準ライブラリ内部にもこれを活用できるケースが多くあり(主にイテレータ)、この提案による仕様を活用するとライブラリの仕様の分量を圧縮することができます(とはいえこれはここではまだ提案されていません)。

さらに、クラス内定義のメンバ関数だけではなくフリー関数および明示的オブジェクト引数を持つ関数としての定義においてもdefault実装を許可することを提案しています。

struct S0 {
  int v;
  S0& operator++() { ++v; return *this; }
  S0 operator++(int) = default; // ok、メンバ関数
};

struct S1 {
  int v;
  S1& operator++() { ++v; return *this; }
  S1 operator++(this S1&, int) = default; // ok、deducing this関数
};

struct S2 {
  int v;
  S2& operator++() { ++v; return *this; }
};
S2 operator++(S2&, int) = default;  // ok、フリー関数

いずれの場合においても、デフォルト実装の関数本体のコンテキストからコピーコンストラクタと対応する前置演算子にアクセスできない場合、暗黙的にdeleteされます。

また、明示的オブジェクト引数を持つ関数としてdefault実装しようとする場合は、明示的オブジェクト引数型がそのクラス型Cに対してC&/const C&である必要があります(すなわち、this C&/this const C&のどちらか)。これは、クラスの特殊メンバ関数default定義時の現在の制約と同じものです。

P3669R0 Non-Blocking Support for std::execution

operation_stateの開始操作がブロッキングするかどうかを取得するインターフェースを追加する提案。

std::executionにおいて、senderreceiverconnectして得られるoperation_statestart関数によって開始されます。このstart関数がどう実行されるか(非同期or同期、あるいは呼び出し元をブロックするかしないか)は実行コンテキスト(scheduler)によって決まります。

using ex = std::execution;

ex::scheduler sched = ...;
ex::sender work = ex::schedule(sched) | ...;
ex::operation_state op = ex::connect(work, receiver{...});

ex::start(op); // start()がすぐ帰るかどうかは分からない

そして、現在のところstart関数が呼び出し元をブロックするかどうかを知る手段はありません。

このことは並行キューの提案(P0260)において問題となり、非ブロッキングtry_pop()/try_push()インターフェースをstd::executionと連携させようとしたときに奇妙なインターフェースとなっています。しかし、この問題は並行キューに限定されるものではありません。

この提案は、operation_stateに対してtry_start()インターフェースを追加することで、startブロッキングに関する情報を取得できるようにしようとしています。

using ex = std::execution;

ex::concurrent_scheduler sched = ...;
ex::sender work = ex::schedule(sched) | ...;
ex::operation_state op = ex::connect(work, receiver{...});

bool started_non_blocking = op.try_start();  // trueが帰った場合ブロッキングせずに開始されている(非同期的に実行されている)

try_start()ブロッキングするかどうかを取得するだけではなく、操作を開始した上で操作の実行がブロッキングしているかどうかを返すものです。

concurrent_schedulerは一緒に追加しようとしているコンセプトで、concurrent_schedulerであるschedulerconnectされたoperation_stateからtry_start()を呼び出すことができます。

P3670R0 Pack Indexing for Template Names

テンプレートパックに対するインデックスアクセスを許可する提案。

C++26ではP2662R3によってパラメータパックに対するインデックスアクセスが可能になっています。

template <typename... T>
constexpr auto first_plus_last(T... values) -> T...[0] {
  return T...[0](values...[0] + values...[sizeof...(values)-1]);
}

int main() {
  //first_plus_last(); // ill formed
  static_assert(first_plus_last(1, 2, 10) == 11);
}

このように、ほとんどのパラメータパックに対してインデックスアクセスが可能になっていますが、唯一それが認められていなかったのがパラメータパックがテンプレートになっているようなパラメータパックに対してです。より具体的には、テンプレートテンプレートパラメータが可変長になっているような場合に現れるパックの事です。

template < template <typename> typename... TT>
struct S {
  using First = TT...[0]; // テンプレートパックのインデックスアクセス
};

この提案は、このTT...[0]のようなテンプレートパックに対するインデックスアクセスを許可しようとしています。

テンプレートパックの各要素は型でも何らかのオブジェクトでもなく、テンプレートです。さらに、P2989R2の採択によってこのテンプレートは型テンプレートだけでなくコンセプトあるいは変数テンプレートも含むことができるようになっており、この提案ではその要素に関係なくテンプレートパックのインデックスアクセスを許可しようとしています。

template <
  typename T, 
  template <typename> concept... C
>
struct S2 {
  static constexpr bool First = C...[0]<T>; // コンセプトテンプレートパックのインデックスアクセス
};

template <
  template <typename T> auto... V
>
struct S3 {
  static constexpr std::size_t L = sizeof(V...[0]); // 変数テンプレートパックのインデックスアクセス
};

P3671R0 Clarifying the interaction of the literal and execution encodings

リテラルエンコーディングと実行エンコーディングが異なる環境について、標準仕様としてのプログラムの動作についての推論の保証をしないようにする提案。

リテラルエンコーディングと実行エンコーディングはどちらもcharエンコーディングの事を言っており、リテラルエンコーディングは文字列リテラルエンコーディングを、実行エンコーディングは実行時のcharエンコーディングを指します。Windows以外のプラットフォームでは基本的にこの二つは一致しています。

この二つの言葉は標準文書で使用されているものの既に混同して使用されており、char文字列を使用するライブラリ機能の検討時に度々問題になってきました。

この提案は、この二つのエンコーディングが一致していない場合のプログラムの動作は推論できないとして、そのような環境におけるプログラムの結果を保証しないようにしようとするものです。

変更としては、リテラルエンコーディングと実行エンコーディングが異なる場合、他方を期待するライブラリ機能にもう片方による文字列を渡すと「予期しない結果が生じたり、未定義動作が発生する可能性がある」という一文を追加します。

なお、ここでの未定義動作とは主に文字化けの事を指しています。

ただし、この変更は規範的な注釈を追加するだけであり、何らかの動作変更を伴うものではありません。なぜなら、そのようなプラットフォームも含めても、現在の仮定(二つのエンコーディングが一致している)の下での規定による実行結果よりも悪くはならないためです。例えば、このことは既にstd::printによって仮定されていますが、Windowsプラットフォームにおいてもstd::printはそのように動作するように実装されています。

Windows環境ではこの仮定は成り立たない場合が良くありますが、Windows環境におけるユニコードサポートの改善やユーザーの習熟(非ASCII文字を扱う場合にロケール関連標準機能を使用しない)などによって、大多数のユーザーにとって支障がない程度にはうまく動作しているため、このような注釈を追加しても問題ないとしています。

P3672R0 On Windows, Systems APIs, Text Encodings, and Pragmatism

パス文字列とユニコードの扱いについての設計指針文書。

この文書は何かを提案するものではなく、標準ライブラリ機能がファイルパスとそのエンコーディングをどのように考慮し、どのように扱うのか、についての基礎知識や設計の方向性・推奨事項などがまとめられた文書です。

特にWindowsというある種特異なプラットフォームの対応をどのように行うべきか、についてがメインの内容です。

パスやそれに近しい文字列(システムインターフェース)を扱うクラスプラットフォームライブラリ的なコードを書く場合に参考になるかもしれません。

おわり

この記事のMarkdownソース