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

文書の一覧

全部で36本あり、SG22(C/C++相互互換性に関する研究グループ)のCの提案を除くと32本になります。

採択された文書

P2313R0 Core Language Working Group "tentatively ready" issues for the February, 2021 meeting

2月の会議で採択されたコア言語のIssue解決の一覧。

解決されたIssueは一件だけです。

  1. 2470. Multiple array objects providing storage for one object
    • unsigned char/std::byteの配列上に別のオブジェクトを構築する時、新しく作成されるオブジェクトにどの配列がストレージを提供したのかが曖昧にならないようにした。

その他文書

N4884 WG21 2021-02 Virtual Meeting Minutes of Meeting

2021年2月22日(米国時間)に行われた、WG21全体会議の議事録。

CWG/LWG/LEWGの投票の様子などが記載されています。

N4885 Working Draft, Standard for Programming Language C++

C++23ワーキングドラフト第4弾。

N4886 Editors’ Report - Programming Languages - C++

↑の変更点をまとめた文書。

2月の会議で採択された提案とコア言語/ライブラリのIssue解決が適用されています。

P0448R4 A strstream replacement using span as buffer

長い間非推奨のまま代替手段のなかったstd::strstreamの代替となるstd::spanによるspanstreamを追加する提案。

以前の記事を参照

このリビジョンでの変更は、LWGのレビューでのフィードバックに基づいて、提案する文言を調整したことです。

この提案は既にこのリビジョンのLWGでのレビューと投票を終えており、全体会議での投票待ちをしています。そこで反対が無ければ、C++23に導入されます。

P0958R3 Networking TS changes to support proposed Executors TS

Networking TSのExecutorの依存部分をP0443のExecutor提案の内容で置き換える提案。

以前の記事を参照

このリビジョンでの変更は、executorコンセプトについてsatisfiesを使用していた所をmodelへ変更したことや、timersocketなどにbasicプリフィックスを加えたことなど、文面の調整です。

P1018R9 C++ Language Evolution status 🦠 pandemic edition 🦠 2021/01–2021/03 - 2021/01–2021/03

EWG(コア言語への新機能追加についての作業部会)が2021/01–2021/03の間に議論した提案やIssueのリストや将来の計画、テレカンファレンスの状況などをまとめた文書。

これらの提案はコンセンサスが得られ、CWGに転送されています。また、その議論や投票の際の賛成・反対のコメントが記載されています。

また、次の提案はライブラリ機能についてのものですが、その内容を言語サポートとすべきかが投票にかけられました。

Executorのプロパティ指定の方法は独立したライブラリ機能として提案されていますが、これを言語サポートする方向でコンセンサスが得られたようです。

P1315R7 secure_clear

特定のメモリ領域の値を確実に消去するための関数secure_clear()の提案。

以前の記事を参照

このリビジョンでの変更は、C言語に向けた文言の表現の選択肢の改善や、選択されなかったものの削除、C/C++委員会での投票結果の記載などです。

P1425R4 Iterators pair constructors for stack and queue

std::stackstd::queueに、イテレータペアを受け取るコンストラクタを追加する提案。

以前の記事を参照

このリビジョンでの変更は、2つに分かれていた機能テストマクロを__cpp_lib_adaptor_iterator_pair_constructor一つに統一した事と、提案する文言の調整です。

このリビジョンは既にLWGのレビューと投票が済んでおり、次の会議の全体投票を待っています。

P1518R1 Stop overconstraining allocators in container deduction guides

P1518R2 Stop overconstraining allocators in container deduction guides

コンテナとコンテナアダプタのクラステンプレート引数推論時の振る舞いを修正し、pmrコンテナの初期化を行いやすくする提案。

std::pmr::monotonic_buffer_resource mr;
std::pmr::polymorphic_allocator<int> a = &mr;
std::pmr::vector<int> pv(a);

// CTADを使用しない構築、全てok
auto s1 = std::stack<int, std::pmr::vector<int>>(pv);
auto s2 = std::stack<int, std::pmr::vector<int>>(pv, a);
auto s3 = std::stack<int, std::pmr::vector<int>>(pv, &mr);

// CTADを使用する構築
auto ds1 = std::stack(pv);
auto ds2 = std::stack(pv, a);
auto ds3 = std::stack(pv, &mr); // NG!

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

※CTAD = Class Template Argument Deduction (クラステンプレートの実引数推定)

stackをはじめとするコンテナアダプタのアロケータ引数は、クラステンプレートのテンプレートパラメータの推論に寄与しません。従って、対応するCTADを使用しない構築の時と同様にコンテナ型からの推論を行うのが望ましいはずです。

namespace std {

  template<typename Container, typename Allocator>
  class stack;

  // stackの2引数推論補助
  template<class Container, class Allocator>
  stack(Container, Allocator)
    -> stack<typename Container::value_type, Container>;
}

このことは何か意図があってのものではなく、単に見落とされただけだと思われるので修正しようとする提案です。

なぜこのようなことが起こるのかというと、コンテナアダプタの推論補助について次のような規定が存在しているためです。

A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true: - ... - It has an Allocator template parameter and a type that does not qualify as an allocator is deduced for that parameter. - ...

[N4861 container.adaptors.general]/4.4

アロケータとしての資格のない型がアロケータ型として渡されている場合、そのアロケータ型がテンプレートパラメータの推論に寄与しないとしても、アロケータ型を受け取る推論補助を無効化してしまいます。

アロケータとしての資格がある型というのは実装定義ですが、最小の要件の一つとして、アロケータ型Aについてメンバ型A::value_typeが利用可能であることがあります([container.requirements.general]/17)。

auto ds3 = std::stack(pv, &mr); // NG!

先程の例のここでは、第二引数の&mrの型はstd::pmr::monotonic_buffer_resource*というポインタ型であって、当然メンバ型を持っておらず、アロケータとしての資格がある型ではないため対応する推論補助は考慮されなくなります。ただ一方で、std::pmr::vector<int>std::pmr::monotonic_buffer_resource*をアロケータとして利用して構築することができます。

さらに、似た問題がstd::vectorそのものにも存在しています。

std::pmr::monotonic_buffer_resource mr;
std::pmr::polymorphic_allocator<int> a = &mr;
std::pmr::vector<int> pv(a);

// CTADによらない構築、全てok
auto v1 = std::vector<int, std::pmr::polymorphic_allocator<int>>(pv);
auto v2 = std::vector<int, std::pmr::polymorphic_allocator<int>>(pv, a);
auto v3 = std::vector<int, std::pmr::polymorphic_allocator<int>>(pv, &mr);

// CTADを使用する構築
auto dv1 = std::vector(pv);
auto dv2 = std::vector(pv, a);
auto dv3 = std::vector(pv, &mr);  // NG!

ここでの問題は先ほどとは少し違っていて、暗黙に生成される推論補助を利用する経路で問題が起きています。

推論補助が無い場合、対応するコンストラクタから推論補助を生成してテンプレートパラメータを推論しようとします。ここで対応しているコンストラクタはアロケータを受け取るコピーコンストラクタです。

namespace std {

  template<typename T, typename Allocator>
  class vector {

    // アロケータを受け取るコピーコンストラクタ
    vector(const vector<T, Allocator>&, const Allocator&);
  };
}

そして、第1引数からはT = int, Allocator = std::polymorphic_allocator<int>が導出され、第2引数からはAllocator = std::pmr::monotonic_buffer_resource*が導出されます。同一のパラメータに対して衝突する候補が発生しているので、推論は失敗しコンパイルエラーとなります。

この提案ではこれらの解決のために、すべてのコンテナのアロケータを受け取るコンストラクタ引数をstd::type_identity_tで包むことでアロケータ引数をCTAD推論の対象から外し、またコンテナアダプタのアロケータ型がある場合の推論補助の要件を「コンテナ型が無く、アロケータ型がある場合」のように少し緩和します。

namespace std {

  template<typename T, typename Allocator>
  class vector {

    // 現在
    vector(const vector<T, Allocator>&, const Allocator&);

    // この提案
    vector(const vector<T, Allocator>&, const type_identity_t<Allocator>&);
  };
}

void stack() {
  std::pmr::monotonic_buffer_resource mr;
  std::pmr::polymorphic_allocator<int> a = &mr;
  std::pmr::vector<int> pv(a);

  // この提案の後では、共にOK
  auto ds3 = std::stack(pv, &mr);
  auto dv3 = std::vector(pv, &mr);
}

std::vectorの場合は、std::type_identity_tによって第2引数の&mrからAllocatorパラメータを推論しなくなるのでAllocatorが一つに定まるようになり、std::stackの場合は文言の変更によって&mrから推論されるアロケータ型の適格性がチェックされなくなるので既存の推論補助によって正しく推論が行われるようになります。

この提案の内容は標準ライブラリの主要な3実装がそれぞれ、誤って 先行して実装しているようです。特に連想コンテナはMSVCとClang(と一部GCCも)すでにこうなっているようです。

P1875R2 Transactional Memory Lite Support in C++

現在のトランザクショナルメモリTS仕様の一部だけを、軽量トランザクショナルメモリとしてC++へ導入する提案。

以前の記事を参照

変更履歴が無いため変更点はよくわかりませんが、おそらくP2066の議論の進行に伴って必要となった変更などを反映したのだと思われます。

P2025R2 Guaranteed copy elision for return variables

NRVO(Named Return Value Optimization)によるコピー省略を必須にする提案。

以前の記事を参照

この提案は主に明示的に注釈することで(N)RVOをオプトインする構文を追加するために、EWGに差し戻されました。

このリビジョンでは、その検討のセクションおよびABIレベルのコピー省略の問題についての説明のセクションを追加しています。

そこでは、[[nrvo]]属性や変数宣言時のreturn注釈、return explicit文、関数宣言(定義)のreturn指定など、様々な構文が検討されています。

P2041R1 template = delete

関数テンプレートがdeleteオーバーロードを提供可能なように、クラス/変数テンプレートでもdelete指定オーバーロード(特殊化)を提供できるようにする提案。

複数の事を意味する同じ名前があり、それらのうちのいくつかは定義されるべきではないとき、現在はその定義を禁止するシンプルで簡易な方法がありません。変数・クラステンプレートについてdelete指定できるようにすることで、一部の特殊化を禁止したり、逆に一部の特殊化だけを許可したりすることができるようになります。

// プライマリ変数テンプレートはdelete、特殊化は許可
template<typename>
int x = delete;
template<>
int x<int> = 5;

// 変数テンプレートの特定の特殊化を禁止
template<typename T>
auto y = T();
template<>
auto y<int> = delete;

// プライマリクラステンプレートはdelete、特殊化は許可
template<typename>
struct s = delete;
template<>
struct s<int> {
};

// クラステンプレートの特殊化を禁止
template<typename>
struct t {
};

template<>
struct t<int> = delete;

非テンプレートのクラスなどでは、deleteするクラスを定義するのではなく最初から定義しないようにすれば同じ効果が得られます。そのため、ここではテンプレートではないものまでdelete指定できるようにすることは提案されていません。

P2066R6 Suggested draft TS for C++ Extensions for Minimal Transactional Memory

現在のトランザクショナルメモリTS仕様の一部だけを、軽量トランザクショナルメモリとしてC++へ導入する提案。

以前の記事を参照

このリビジョンの変更点は、R5で標準ライブラリのもののほとんどがatomicブロックでの使用を許可されましたが、そのうち同期の問題が発生しうるものを除外した事です。例えば、shared_ptrsynchronus_memory_resourceタイムゾーンのデータベースなどが該当します。

P2093R5 Formatted output

p2093r4.html)

std::formatによるフォーマットを使用しながら出力できる新I/Oライブラリstd::printの提案。

前回の記事を参照

このリビジョンでの変更は、ostreamを取るオーバーロードをヘッダ分けしたことと、ostreamを取らないものの配置するヘッダの候補をリスト化した事です。現在は<io>に配置することを提案しています。

この提案はSG16での議論とレビューを終えて、LEWGに送られました。非常に素早く作業が進行しているため、C++23に入る可能性は高そうです。

P2210R2 Superior String Splitting

現状のviews::splitの非自明で使いにくい部分を再設計する提案。

前回の記事を参照

このリビジョンでの変更は、現在のviews_splitlazy_split)にある問題の解決を含んだうえで文言を調整し、実装例を追記した事です。

この提案はLEWGでの議論が完了しLWGに転送する最終投票を待っていますが、C++20にDRとして適用するためにLWGで先行してレビューが完了しています。LEWGでの投票が問題なく終われば、C++23(C++20)導入に向けて全体会議での投票に進みます。

P2242R2 Non-literal variables (and labels and gotos) in constexpr functions

constexpr関数において、コンパイル時に評価されなければgotoやラベル、非リテラル型の変数宣言を許可する提案。

以前の記事を参照

このリビジョンでの変更は、機能テストマクロに関する議論を追記したことと、サンプルと文言の微修正です。

この提案の修正は実際にはconstexpr関数で実行可能なものを増やしているわけではありませんが、__cpp_constexprの値を微増させています。検出が必要になるとは思えないけれどconstexprの許容範囲を広げるときに値を更新する方向性を支持している、ということが説明されています。

P2266R1 Simpler implicit move

return文における暗黙のムーブを改善する提案。

以前の記事を参照

このリビジョンでの変更は、提案する文言のリファクタリングと、ラムダの内部でローカル変数がスローされるときにも、スローされる変数を暗黙ムーブするかのような文言になっている部分を修正する文言を追加した事です。

P2299R0 mdspan and CTAD

提案中のstd::mdspanのCTAD対応についての問題を報告する文書。

P0009R10で提案されているstd::mdspanは、std::basic_mdspanを基礎として、そのエイリアスとしてstd::mdspanを定義しています。

template <class ElementType, ptrdiff_t... Extents>
using mdspan = basic_mdspan<ElementType, extents<Extents...>>;

これは例えば次のように利用できます

int main() {
  // 何かメモリ領域
  double* data = ...;

  // 静的サイズ
  mdspan<double, 64, 64> a1(data);
  // 動的サイズ
  mdspan<double, dynamic_extent, dynamic_extent> a2(data, 64, 64);
  // 静的+動的サイズ
  mdspan<double, 64, dynamic_extent> a3(data, 64);
}

C++20からはエイリアステンプレートに対するCTADが利用可能となっているので、上記の2つめの例は次のように書けるはずです。

int main() {
  // 何かメモリ領域
  double* data = ...;

  // 動的サイズ
  mdspan a2(data, 64, 64);
}

冗長なdynamic_extent指定を排除し非常に読みやすくなります。しかし、これはどうやら意図通りに動かないようです。

ここでは、std::mdspan<double>を推論した後、std::basic_mdspan<double, extents<>>を推論しインスタンス化します。これはstd::basic_mdspanの動的エクステントのコンストラクタでstatic_assertに引っかかりコンパイルエラーを起こします。

単純には、std::mdspanに推論補助を追加すればこの問題の解決は図れるはずですが、現在の仕様ではエイリアステンプレートに推論補助を追加できません。かといって、std::mdspanを単独のクラスにしてしまうとstd::basic_mdspanとの相互運用性がなくなるなど様々な問題が発生します。

この提案はこの問題の周知を図り、よりよい解決策を募るものです。

P2314R1 Character sets and encodings

規格文書中の ~ character setという言葉を明確に定義し直す提案。

以前の記事を参照

このリビジョンでの変更は、文言の修正とP2297R0との目的の差異を説明するセクションの追加、ロケール依存の実行文字集合execution (wide) character set)の文言の場所をライブラリに移動した事です。

この提案は、既存の振る舞いを維持しながら、言葉の定義を明確にすることで字句解析におけるコア言語のルールの再構築を目指すものです。従って、EWGの負担は軽くなる筈、という事が説明されています。

P2322R1 ranges::fold

rangeアルゴリズムであるranges::foldの提案。

以前の記事を参照

このリビジョンでの変更は、以前にregular_invocableコンセプトを用いていたところをinvocableコンセプトに変更した事(regularであることは必要なかったため)と、以前にfold_firstなどとしていた初項を範囲から補う関数ファミリを初項の提供有無でのオーバーロードに変更したことです。

以前に書いたサンプルは次のようになります。

std::vector<int> vec = {1, 2, 3, 4, 5};

int sum1 = std::ranges::fold(vec, 0, std::ranges::plus{});
int sum2 = std::ranges::fold(vec, std::ranges::plus{});
// sum1 == sum2 == 15

std::vector<std::string> vec2 = {"aaa", "bbb", "ccc"};
std::string concat1 = std::ranges::fold(vec2, std::ranges::plus{});
// concat1 == "aaabbbccc"

std::string concat2 = std::ranges::fold_right(vec2, std::string{}, std::ranges::plus{});
std::string concat3 = std::ranges::fold_right(vec2, std::ranges::plus{});
// concat2 == concat3 == "cccbbbaaa"

P2325R1 Views should not be required to be default constructible

Viewとみなされる型にデフォルト構築可能性を要求しない様にする提案。

以前の記事を参照

このリビジョンでの変更は、パイプラインでの左辺値/右辺値の固定エクステントstd::spanの扱いに関する例を追加した事です。

std::spanviewであるはずなのですが、固定エクステントの場合はデフォルト構築できないようになっています。これによって、右辺値と左辺値でそれぞれ異なる、非効率な結果が得られます

std::span<int, 5> s = /* ... */;

// spanはviewではないため、transform_viewはコピーする代わりに`ref_view<span<int, 5>>`を保持する
// sの寿命が先に尽きる場合、これはダングリング参照となる
auto lvalue = s | views::transform(f);

// spanはborrowed_rangeであるため、これはコンパイル可能
// ただ、sをコピーするのではなく、subrange<span<int, 5>::iterator>を保持する
auto rvalue = std::move(s) | views::transform(f);

左辺値の場合はダングリングの危険があり、追加の間接参照が必要となります。右辺値の場合はダングリングの危険はないものの、2つのイテレータを保持する必要からspanを直接保持する場合の倍のストレージを使用します。この値カテゴリの違いによる異なった振る舞いはどちらにせよ非効率で、固定エクステントspanviewだった場合のデメリットよりもひどいものです。

固定エクステントのspanは正当な理由でデフォルトコンストラクタを持たず、viewにするためにデフォルトコンストラクタを構築するとユーザーが気を付けてチェックしなければならない追加の状態が導入されます。spanの全ての操作に文書化の必要がある事前条件が課されることになり、これはまたすべてのviewにも当てはまっています。

この観点からもやはり、viewコンセプトのデフォルト構築要求は不要であるといえます。

P2328R0 join_view should join all views of ranges

std::ranges::join_viewの制約を緩和して、prvalueviewではないrangeを平坦化できるようにする提案。

join_viewrangerangeとなっているシーケンスを1つのrangeに平坦化するもので、他のところではflattenとも呼ばれています。

ここに1つ機能を加えて、要素(内側のrange)を変換しつつ平坦化するflat_mapというものがあります。そのまま書くと、C++20時点では次のようになるはずです。

template<std::ranges::range R, std::invocable<std::ranges::range_value_t<R>> F>
  requires std::ranges::range<std::ranges::range_value_t<R>> and
           std::ranges::range<std::invoke_result_t<F, R>>
auto flat_map(R&& r, F&& f) {
  return r | std::views::transform(f) | std::views::join;
}

このようなrangeアダプタのチェーンはほとんどの場合にコンパイルエラーとなります。

現在のjoin_viewが平坦化できるのは次の2つのどちらかです。

  • glvaluerangerange
  • prvalueviewrange

r | std::views::transform(f)の結果はfの結果のrangeによるprvalueviewとなり、fの結果のrangeprvalueviewとならない場合にコンパイルエラーとなります。少し考えてみると、これはかなり一般的なユーズケースであることがわかると思います(fの結果として範囲を返すとき、std::vectorを使いたくなりませんか?)。

現在のjoin_viewprvalueな(viewではない)rangerangeサポートが欠けていることによってこの問題は発生しています。

Range-v3ライブラリでは、views::cache1(提案されている名前はviews::cache_latest)というviewを間に挟むことでこの問題を解決し、views::flat_mapを導入しています。

cache1は元のrangeイテレータの間接参照結果をキャッシュとして持っておくことによって、prvaluerangerangeglvaluerangerangeに変換するものです。これによってjoin_viewはあらゆるケースで平坦化できるようになります。

ただ、cache1cache_latest)にはいくつかの問題があります

  • イテレータoperator*() conststd::indirectly_readbleコンセプトで要求される)は内部でキャッシュを操作するため、スレッドセーフではない。
    • 標準ライブラリのconstメンバ関数はスレッドセーフであることを表明している。
  • cache1の理解や発見は自明ではない。
    • なぜそれが必要なのかのヒントはなく、join_viewの使用を通してその存在の必要性を納得するしかない。

現在のjoin_viewは、prvalueviewrangeを処理する際に、内側のprvalueviewを内部でキャッシュしておくことによって処理しています。この提案では、cache_latestを導入する代わりに、このキャッシュ機構をprvalueな(viewではない)rangerangeに対しても行うことで上記の問題の解決を図ります。

ただし、この場合のキャッシュは伝播しません。すなわち、そのようなキャッシュを保持しているjoin_viewをコピー/ムーブすると、コピー/ムーブ先ではキャッシュは空となります。これによって、join_viewのコピー/ムーブが元のrangeの生成するものに依存しないことが保証されています。また、このようなキャッシュをしている場合のjoin_viewinput_rangeであり、begin()の呼び出しは1度しか行えません(最初のbegin()の呼び出し後にrangeとして使用不可能となる)。

P2330R0 WG21 2021-02 Virtual Meeting Record of Discussion

2月のWG21本会議における発言記録。

コア言語に関して

  • 昨年11月の本会議で採択されたP2238R0にあるコア言語IssueがC++20に対するDefect Report(DR)として扱うことを決定。
  • P1787R6の内容をDRとして扱うことを決定(バージョンは指定されていない)。
  • P2313R0の内容をDRとして扱うことを決定(バージョンは指定されていない)。

ライブラリ機能に関してはP0533R7 constexpr for <cmath> and <cstdlib>(リンクはR6)がリジェクトされた過程が記載されています。

それによれば、精度低下によるエラーが定数評価を妨げる可能性があるという問題提起があり、その解決策について十分に議論が尽くされておらず、このままだと実装が困難となるか実装間で相違が発生する可能性があるという点が懸念され、投票の結果反対および中立が多く出たため、リジェクトされたようです。

P2332R0 Establishing std::hive as replacement name for the proposed std::colony container

提案中のstd::colonyの名前をstd::hiveに変更する提案。

LEWGの議論の過程で、std::colonyという名前に関して何人かのメンバが次のような疑問を抱いているようです

  • colonyという単語は多くの意味を含んでいる
  • colonyという名前は馴染みがなく、一般的では無い

色々な名前の候補が上がった結果、hive(ミツバチの巣)が選ばれたようです。これにはLEWGの多くのメンバとstd::colonyの作者(著者)の方も同意を示しているようです。

colony(集団・居住地・村など)のお気持ちは

  • コンテナそのものがコロニー
  • 記憶ブロック(配列)が家
  • 要素の記憶域が部屋
  • 要素は人
  • 人の行き来(要素の挿入・削除)に対して家や部屋に変化はない(記憶域と配列は安定)

hiveのお気持ちは

  • コンテナは巣箱
  • 1記憶ブロック(配列)が1つの巣板
  • 要素の記憶域は6角形のセル
  • 要素はミツバチ

hiveではミツバチがセルに住んでいる訳ではないことから要素の安定性に関しての表現が足りていないとのことですが、LEWGでは名前の意味の単純化のために許容されたようです。

また、std::colonyが力を発揮する用途がイテレーション時に要素の挿入・削除が頻繁に起こるようなケースであり、蜂の巣の出入りの忙しさがこの側面を表現しているとして好まれたようです。

P2333R0 2021 Winter Library Evolution Poll Outcomes

2021年の冬(1月から3月にかけて)に行われた、LEWGの全体投票の結果。

以下の9つの提案が投票にかけられ、どれもLWGに転送されることが可決されています。

P2334R0 Add support for preprocessing directives elifdef and elifndef

#elifでマクロの定義の有無で条件分岐する糖衣構文となるプリプロセッシングディレクティブである#elifdef/#elifndefの提案。

#ifdef/#ifndef#if defined(macro_name)/#if !defined(macro_name)の糖衣構文として随分前から利用可能ですが、#elif defined(macro_name)/#elif !defined(macro_name)に対応する糖衣構文はありません。

このような構文の一貫性のなさは、一部のユーザーにとっては予測可能ではありません。

#elifdef/#elifndefを追加し一貫性を改善することで、ユーザビリティの向上を図る提案です。

#ifdef M1
...
#elif defined(M2)
...
#endif

// ↑が↓こう書ける

#ifdef M1
...
#elifdef(M2)
...
#endif

この提案はすでにC23に導入されており、C/C++間の互換性確保のためにC++に対しても提案されているものです。

P2338R0 Freestanding Library: Character primitives and the C library

<charconv>std::char_traitsをはじめとするいくつかのヘッダをフリースタンディングライブラリ指定する提案。

C/C++の標準ライブラリにはシステムプログラムにおいて有用な機能が多数存在していますがそれらのライブラリ機能は必ずしもフリースタンディング指定されていないため、コンパイラ拡張などの移植性の乏しい形で利用するか、自分で実装するしかない場合が多いようです。

そのようなライブラリ機能のうち、OSのサポートや動的メモリ確保を必要とせずに実装できるものをフリースタンディングライブラリとして提供することによって、より高レベルにシステムプログラムを記述し、かつそれを移植可能にすることができます。

この提案は、フリースタンディングライブラリをOSや動的なメモリ確保に依存しない標準ライブラリの最大のサブセットとして提供することを目的とした一連の取り組みの一環です。

この提案でフリースタンディング指定を提案されているのは次のものです

  • <string>
    • std::char_traits
  • <charconv>
  • <cinttypes>
  • <cstdlib>, cmath
  • <cstring>
  • <cwchar>
  • <cerrno>, <system_error>
    • errnoを除く各種エラー定義マクロとstd::errc

この提案は同時にC標準に対しても行われています。

P2339R0 Contract violation handlers

契約プログラミングについて、契約違反を起こしたときに終了するのではなく継続する場合のユースケースについて説明した文書。

C++20でリジェクトされたコントラクト仕様にも、現在議論されているものにも、契約違反が起きた時のデフォルトの対応はstd::terminate()std::abort()を実行してその場で終了することです。

しかし、契約違反が起きた時でも実行を継続したい場合があり、C++20の仕様には違反継続モードがあり、現在の議論では例外を投げる、return;するなどが議論されているようですが、どちらも反対意見があるようです。

この文書はC++23の契約プログラミング導入にむけて、契約違反時に実行を継続するユースケースやその利点についてSG21内で共通の理解を得るためのものです。

P2340R0 Clarifying the status of the ‘C headers’

現在非推奨とされているCヘッダを相互運用の目的で使用可能なようにする提案。

ISO規格の文脈での非推奨(deprecated)という言葉は、使用されない・推奨されない・将来削除されうる、などの意味を持ちます。C++が規格化されて以降、Cのヘッダは非推奨という扱いで規定されており、C++のエコシステムとして提供はされているが使用しづらいものとなっていました。

C++におけるCヘッダの主な役割は、C言語との相互運用性およびC言語のABIとリンケージ規則を使用する他のシステムとの相互運用のためにあり、非推奨なのは相互運用を目的としないC++コードでの利用時だけなはずです。この提案は、CヘッダをCおよびその互換システムとの相互運用の目的のために利用することができるように、Cヘッダの非推奨を解除してCのヘッダ群がC++のエコシステムとして提供されることを明確にしようとする提案です。

なお、ここでのCヘッダとは<cxxx>という形式のC++におけるC互換ヘッダではなく、Cの標準ライブラリヘッダとして定義されている<xxx.h>の形式のものを指しています。

この提案の後でも、Cコードとして有効である必要がないC++コードでのCヘッダの使用は推奨されません。あくまでCのABIおよびリンケージを利用するシステムとの相互運用性確保のための変更です。

P2400R0 Library Evolution Report

2020年10月27日~2021年2月16日の間の、LEWGの活動記録。

LEWGにおいて議論されている機能の現状について、及びレビューや投票を行った提案のリストなどがあります。

Executor

P0443R14のレビューが完了し、そこで得られたフィードバックに基づいてP0443R15を準備中のようです。投稿され次第、再びレビューが行われる予定です。

コルーチンのライブラリサポート

P2168R1std::generator)の改訂版が近々提出される予定で、そのレビューはすぐに行われる予定です。

しかし、他の提案は一度のレビューの後改訂されておらず、std::generator以外のコルーチン関連のライブラリサポートの議論は止まっているようです(ただし、Executorに依存しているために止まっているものがある可能性があります)。

Networking TS

Networking Study Groupで議論が続いており、まだLEWGに提出されていません。これはExecutorに依存していますが、大きな機能であるために並行して作業が可能なはずです。

2021年春頃までにLEWGでのレビューに進めない場合、C++23に間に合わなくなる可能性があります。

標準ライブラリのモジュール化

2020年春以降、関連した活動が見られないようです。このまま議論もされなければ、C++23には間に合いません。

ranges

P2214R0をレビューし、この提案の方向性でのRangeライブラリの拡張をLEWGは支持しています。

P2210R0std::ranges::split_viewの改善)はLEWGにおける最終レビューを通過し、LWGに転送するための電子投票にかけられる予定です。前回の電子投票の期限に間に合わなかったためまだ投票は行われていませんが、2021年春頃には投票が開始される予定です。

ranges関連の提案をよく書いている著者の方が協力的かつ活発なためranges関連のレビューはスムーズに進行しており、提案は迅速に処理されているようです。

format

P2216R2std::foramtの改善)はLEWGにおける最終レビューを通過しており、2021年1月に電子投票にかけられました。この提案にはC++20に対する破壊的な変更が含まれていますが、既存実装が無いために影響は無いと判断されました。

P2093R2std::print)はまだLEWGで議論の真っ最中ですが、著者の方の応答性が高いために作業は順調に進行しているようです。早ければ2021年春頃にLWGに転送される可能性があるようです。

Text and Unicode

P1885R3がLEWGに提出されており、メーリングリストレビューおよびテレカンレビューを完了したようです。改善の必要があったため、改訂待ちをしています。

フリースタンディング

P1462R5<utility>, <ranges>, <iterator>のフリースタンディングサポート)のLEWGでの最終レビューが完了し、2021年1月にLWGに転送するための最後の電子投票にかけられました。