文書の一覧
採択されたものはありません、全部で58本あります。
が、SG22(C/C++相互互換性に関する研究グループ)経由でCの提案が含まれているので、そこからC++に対してのものでないものを除くと48本になります。
- N4880 PL22.16/WG21 agenda: 22 February 2021, Virtual Meeting
- N4881 WG21 virtual meetings: 2021-02, -06, and -10
- N4882 WG21 admin telecon meetings: 2021-02, -05, and -09
- N4883 WG21 February 2021 admin telecon minutes
- P0401R6 Providing size feedback in the Allocator interface
- P0448R3 A strstream replacement using span as buffer
- P0849R7 auto(x): decay-copy in the language
- P1018R8 C++ Language Evolution status 🦠 pandemic edition 🦠 2020/11–2021/01
- P1072R7 basic_string::resize_and_overwrite
- P1322R3 Networking TS enhancement to enable custom I/O executors
- P1425R3 Iterators pair constructors for stack and queue
- P1659R2 starts_with and ends_with
- P1659R3 starts_with and ends_with
- P1682R3 std::to_underlying
- P1885R5 Naming Text Encodings to Demystify Them
- P1951R1 Default Arguments for pair's Forwarding Constructor
- P2047R1 An allocator-aware optional type
- P2066R5 Suggested draft TS for C++ Extensions for Minimal Transactional Memory
- P2093R4 Formatted output
- P2128R3 Multidimensional subscript operator
- P2162R2 Inheriting from std::variant (resolving LWG3052)
- P2164R4 views::enumerate
- P2195R2 Electronic Straw Polls
- P2216R3 std::format improvements
- P2231R1 Missing constexpr in std::optional and std::variant
- P2234R1 Consider a UB and IF-NDR Audit
- P2242R1 Non-literal variables (and labels and gotos) in constexpr functions
- P2249R0 Mixed comparisons for smart pointers
- P2280R1 Using unknown references in constant expressions
- P2281R1 Clarifying range adaptor objects
- P2286R1 Formatting Ranges
- P2287R1 Designated-initializers for base classes
- P2289R0 2021 Winter Library Evolution Polls
- P2290R0 Delimited escape sequences
- P2291R0 Add Constexpr Modifiers to Functions to_chars and from_chars for Integral Types in Header
- P2295R0 Correct UTF-8 handling during phase 1 of translation
- P2297R0 Wording improvements for encodings and character sets
- P2301R0 Add a pmr alias for std::stacktrace
- P2302R0 Prefer std::ranges::contains over std::basic_string_view::contains
- P2314R0 Character sets and encodings
- P2315R0 C++ Standard Library Issues to be moved in Virtual Plenary, Feb. 2021
- P2316R0 Consistent character literal encoding
- P2317R0 C++ - An Invisible foundation of everything
- P2320R0 The Syntax of Static Reflection
- P2321R0 zip
- P2322R0 ranges::fold
- P2324R0 Labels at the end of compound statements (C compatibility)
- P2325R0 Views should not be required to be default constructible
- 次
N4880 PL22.16/WG21 agenda: 22 February 2021, Virtual Meeting
2021年2月22日 11:00 (北米時間)に行われるWG21本会議のアジェンダです。
C++23のための2回目の全体会議です。
N4881 WG21 virtual meetings: 2021-02, -06, and -10
今年のWG21全体会議の予定表。
↑の2月のものを除くと、6月と10月に予定されています。どちらもオンラインで行われることが決定しています。
N4882 WG21 admin telecon meetings: 2021-02, -05, and -09
全体会議に共通する大まかな進行表。
N4883 WG21 February 2021 admin telecon minutes
2021年2月8日に行われた、WG21各SG等の責任者によるミーティングの議事録。
P0401R6 Providing size feedback in the Allocator interface
アロケータが実際に確保したメモリのサイズをフィードバックすることのできるメモリ確保インターフェースを追加する提案。
以前の記事を参照
- P0401R4 Providing size feedback in the Allocator interface - [C++]WG21月次提案文書を眺める(2020年11月)
- P0401R5 Providing size feedback in the Allocator interface - [C++]WG21月次提案文書を眺める(2020年12月)
このリビジョンでの変更は、LWGのフィードバックを受けて提案する文言を改善したことです。
この提案はすでにLWGでのレビューが完了しており、そこではこの提案はC++23に導入する事に全会一致でのコンセンサスが取れています。そのため、次の全体会議(2021年6月)で全体投票にかけられ、問題がなければC++23に入る見込みです。
P0448R3 A strstream replacement using span as buffer
長い間非推奨のまま代替手段のなかったstd::strstream
の代替となるstd::span
によるspanstream
を追加する提案。
std::strstream
は事前に確保された固定長のバッファを受け取りそれを利用したストリームを構築できるものでしたが、同時に可変長の内部バッファを扱う機能も持っており(コンストラクタでスイッチする)、その結果.str()
から返されるchar*
の指すメモリの管理責任が不明瞭になっていました。また、可変長バッファを使用する場合は.freez(false)
をしてからデストラクタを呼び出す必要があるのですがわかりづらく、忘れられることが多かったようです。
このように、使いづらくメモリリークの危険性を備えていることからC++98でstd::strstream
は非推奨とされました。ただし、固定長バッファからストリームを構築し、そのバッファを文字列として参照する、という機能は有用で完全に代替するものが無かったことから削除されずに今日まで残っています。
文字列ベースのストリームという機能はstd::stringstream
が代替として利用できますが、固定長バッファによるストリームを代替する機能はありませんでした。
この提案はstd::strstream
の機能の一つだった、事前に確保された固定サイズのバッファを用いたストリームをstd::span
を利用して実現するものです。
ヘッダ<spanstrem>
に以下のものが追加されます。
std::basic_spanbuf
std::spanbuf
std::wspanbuf
std::basic_ispanstream
std::ispanstream
std::wispanstream
std::basic_ospanstream
std::ospanstream
std::wospanstream
std::basic_spanstream
std::spanstream
std::wspanstream
// 入力ストリームのサンプル char input[] = "10 20 30"; std::ispanstream is{std::span<char>{input}}; int i; is >> i; ASSERT_EQUAL(10,i); is >> i; ASSERT_EQUAL(20,i); is >> i; ASSERT_EQUAL(30,i); is >>i; ASSERT(!is);
// 出力ストリームのサンプル char output[30]{}; // zero-initialize array ospanstream os{span<char>{output}}; os << 10 << 20 << 30; auto const sp = os.span(); ASSERT_EQUAL(6, sp.size()); ASSERT_EQUAL("102030", std::string(sp.data(),sp.size())); ASSERT_EQUAL(static_cast<void*>(output), sp.data()); // ポインタの比較 ASSERT_EQUAL("102030", output);
P0849R7 auto(x): decay-copy in the language
明示的にdecay-copyを行うための構文を追加する提案。
以前の記事を参照
- P0849R4 auto(x): decay-copy in the language - [C++]WG21月次提案文書を眺める(2020年10月)
- P0849R5 auto(x): decay-copy in the language - [C++]WG21月次提案文書を眺める(2020年11月)
- P0849R6 auto(x): decay-copy in the language - [C++]WG21月次提案文書を眺める(2020年12月)
このリビジョンでの変更は、decltype(auto(...))
とdecay_t
との構文比較表の追加とLWG Issue 3491に関する文言を別のところで議論することにしたこと、および関連しそうな機能(P2255R0 A type trait to detect reference binding to temporaryとP0847R6 Deducing this)との相互作用についての追記です。
この提案は、ライブラリパートについてLEWGからLWGへ転送され、そこでのレビューが完了次第CWGに送られ最後のレビューを迎えます。
P1018R8 C++ Language Evolution status 🦠 pandemic edition 🦠 2020/11–2021/01
EWG(コア言語への新機能追加についての作業部会)が2020/11–2021/01の間に議論した提案やIssueのリストや将来の計画、テレカンファレンスの状況などをまとめた文書。
前回と比べると、多くのIssueに関して議論をしていたようです。
P1072R7 basic_string::resize_and_overwrite
std:string
に領域(文字長)を拡張しつつその部分を利用可能にする為のメンバ関数resize_and_overwrite()
を追加する提案。
以前の記事を参照
このリビジョンでの変更は、記述の修正がメインの様です。
P1322R3 Networking TS enhancement to enable custom I/O executors
Networking TSのI/Oオブジェクトをio_context
だけではなく、任意のExecutorによって構築できるようにする提案。
以前の記事を参照
このリビジョンでの変更は、AcceptableProtocol要件に入れ子型::socket_for<Executor>
を追加し、ip::tcp,ip::udp
クラスがそれを備えるようにしたことなどの、提案する文言の調整です。
P1425R3 Iterators pair constructors for stack and queue
std::stack
とstd::queue
に、イテレータペアを受け取るコンストラクタを追加する提案。
以前の記事を参照
このリビジョンでの変更は、アロケータ型も含めてテンプレートパラメータを推論するための推論補助を追加したことです。
この提案はLEWGからLWGへ送られ、LWGでのレビューの結果、まだ未公開のR4がC++23入りのコンセンサスを得たようです。おそらく次の全体会議(2021年6月)でC++23に採択されます。
P1659R2 starts_with and ends_with
P1659R3 starts_with and ends_with
任意の範囲に対して動作するstd::ranges::starts_with/std::ranges::ends_with
の提案。
以前の記事を参照
R2およびR3での変更は、提案する文言の修正がメインです。
この提案はすでにLWGでのレビューを終えており、LWGでのC++23入りのコンセンサスを得ています。おそらく次の全体会議(2021年6月)でC++23に採択されます。
P1682R3 std::to_underlying
列挙型の値からその基底の整数型への変換を行うstd::to_underlying
の提案。
以前の記事を参照
このリビジョンでの変更は、機能テストマクロの修正など提案する文言の調整のみです。
この提案は2021年2月22日(米国時間)に行われた全体会議でC++23入りが承認されています。次のワーキングドラフトからC++23に反映されます。
P1885R5 Naming Text Encodings to Demystify Them
システムの文字エンコーディングを取得し、識別や出力が可能なライブラリを追加する提案。
以前の記事を参照
- P1885R3 Naming Text Encodings to Demystify Them - [C++]WG21月次提案文書を眺める(2020年9月)
- P1885R4 Naming Text Encodings to Demystify Them - [C++]WG21月次提案文書を眺める(2020年11月)
このリビジョンでの変更は以下のものです。
- エンコーディング名として
char*
を返す動機の説明の追記 - 文言の改善と、フリースタンディング関連の文言の削除
- systemという言葉のenvironmentへの置き換え
- 名前の照合に問題のある古いエンコーディングを除外
LEWGでの最初のレビューの結果、提案の方向性への支持とこの提案のために作業時間をかけることへのコンセンサスが得られています。とはいえ、まだLEWGでの議論は続きます。
P1951R1 Default Arguments for pair's Forwarding Constructor
std::pair<T1, T2>
のforwarding constructor(要素型に変換可能な値を転送して構築するコンストラクタ)のテンプレートパラメータにデフォルト引数としてT1, T2
を指定する提案。
現在のstd::pair
では次のようなコードを書くと、見えない所にオーバーヘッドを埋め込むことになります。
// std::stringとstd::vector<std::string>の一時オブジェクトが作られ、コピーされる std::pair<std::string, std::vector<std::string>> p("hello", {});
std::pair<T1, T2>
について、上記コードのコンストラクタのオーバーロード解決では、次の2つのコンストラクタが考慮されることになります。
explicit(see below) constexpr pair(const T1& x, const T2& y); template <class U, class V> explicit(...) constexpr pair(U&& x, V&& y);
しかし、2つ目の候補は、第二引数が{}
のみであることからV
の推定ができないため候補から外されます。結果1つ目の候補が選ばれ、一時オブジェクトの作成とそこからのコピー構築が行われます。
この場合に2つ目のコンストラクタを選択しようとする場合、次のように書く必要があります。
std::pair<std::string, std::vector<std::string>> p("hello", std::vector<std::string>{});
しかしこの構文は冗長でユーザーフレンドリーではありません。
この提案は2つ目のコンストラクタ(forwarding constructor)のデフォルトテンプレートパラメータとしてT1, T2
を入れておくことで、最初の例のように書いた場合でも常にforwarding constructorが選択されるようにするものです。
2つ目の形式のコンストラクタは次のように変更します。
template <class U = T1, class V = T2> explicit(...) constexpr pair(U&& x, V&& y);
たったこれだけの事で、{}
の初期化子の使用が意図通りになるようになります。std::pair
の構築で{}
を使用している既存のコードの振る舞いが変更され、一時オブジェクトのコピーからムーブまたは完全転送による構築に切り替わります。これは明らかに望まれる動作であり、それによって壊れるコードはないものと思われます。
この提案の内容とC++23導入を目指すことはLEWGにおいて合意が取れており、LWGに転送するためにLEWGでの投票を待っている所です。
P2047R1 An allocator-aware optional type
Allocator Awareなstd::optional
である、std::pmr::optional
を追加する提案。
Allocator Awareなオブジェクトとは、次の要件を満たすものです。
- 一度構築されると、そのアロケータは変更されない。
- オブジェクトのコンストラクタはuses-allocator構築で指定される2つの方法のいずれかでアロケータを受け取る。
- これによって、コンテナの要素となるときにコンテナのアロケータが伝播される。
- Allocator Awareな型を要素としうるオブジェクトはそれ自体がAllocator Awareであり、受け取ったアロケータを要素に伝播させなければならない。
現在のstd::optional
はAllocator Awareではなく、上記ルールのいずれも満たしません。有効値を破棄して無効状態となるとそこで使用されていたアロケータを忘れてしまい、uses-allocator構築のプロトコルに従ったアロケータを受け取るコンストラクタを持っていないため、コンテナで使用されたときに要素のオブジェクトに適切にアロケータが伝播しません。
結果、現在のstd::optional
はコンテナで使用するときにアロケータを適切に管理できず、例えばpmr
コンテナの不変条件である全ての要素が同じアロケータを使用する、という条件を満たすことができません(これは未定義動作につながります)。
この提案のstd::pmr::optional
はAllocator Awareな要素型を持つときに上記3つのルールに従うようにすることで、自身もAllocator Awareとなるものです。そのために、構築に使用されたアロケータを内部で保持しています。
std::pmr::optional
の基本設計は単純で、全てのコンストラクタでアロケータを受け取るようにした上で、受けたアロケータを使用して要素を構築するようにします。また、そのように渡されたアロケータを内部で保持し、有効値の再構築時に使用します。
ただし、対象とするアロケータはstd::pmr::polymorphic_allocator
のみです。これによってアロケータの型がstd::optional
の型に現れることを防止します(polymorphic_allocator
はC++20での改修によってこのような型に依存しない運用が可能になっています)。
これは従来のstd::optional
を置き換えるものではなく、std::optional
の振る舞いを変更するものでもありません。また、std::pmr::optional
がAllocator Awareでない型を保持する場合は従来のstd::optional
に切り替わります。すなわち、std::pmr::optional
はAllocator Awareな型を要素とする場合にのみ、std::optional
と異なる振る舞いをします。
std::pmr::optional
はジェネリックなコードで(特にコンテナの要素型として)使用して、Allocator Awareな型を要素とする場合に適切にアロケータが伝播されるようにするものです。そして、std::pmr::optional
はstd::optional
の単なるエイリアスではなく別の型として実装されることになります。
なお、std::pmr::optional
はAllocator Awareな型を要素とする場合でも、そのアロケータを使用して自身のためのストレージを確保するものではありません。要素のストレージは従来通り自身の内部にあります。
P2066R5 Suggested draft TS for C++ Extensions for Minimal Transactional Memory
現在のトランザクショナルメモリTS仕様の一部だけを、軽量トランザクショナルメモリとしてC++へ導入する提案。
以前の記事を参照
- P2066R2 Suggested draft TS for C++ Extensions for Minimal Transactional Memory - [C++]WG21月次提案文書を眺める(2020年05月)
- P2066R3 Suggested draft TS for C++ Extensions for Minimal Transactional Memory - [C++]WG21月次提案文書を眺める(2020年09月)
- P2066R4 Suggested draft TS for C++ Extensions for Minimal Transactional Memory - [C++]WG21月次提案文書を眺める(2020年10月)
このリビジョンの変更点は、atomicブロックでのthrow
式のうち、ブロック内で処理される例外は未定義動作ではないとされたこと、ほぼ全ての標準ライブラリ関数はatomicブロック内で使用可能とされたことです。
P2093R4 Formatted output
std::format
によるフォーマットを使用しながら出力できる新I/Oライブラリstd::print
の提案。
前回の記事を参照
- P2093R0 Formatted output - [C++]WG21月次提案文書を眺める(2020年6月)
- P2093R1 Formatted output - [C++]WG21月次提案文書を眺める(2020年7月)
- P2093R2 Formatted output - [C++]WG21月次提案文書を眺める(2020年10月)
- P2093R3 Formatted output - [C++]WG21月次提案文書を眺める(2021年1月)
このリビジョンでの変更は、_isatty
を使って処理の例示を行なっていた所をGetConsoleMode
に置き換えた事です。
この提案はSG16での議論とレビューを終えて、LEWGに送られたようです。
P2128R3 Multidimensional subscript operator
多次元コンテナサポートのために添字演算子([]
)が複数の引数を取れるようにする提案。
前回の記事を参照
- P2128R1 Multidimensional subscript operator - [C++]WG21月次提案文書を眺める(2020年5月)
- P2128R2 Multidimensional subscript operator - [C++]WG21月次提案文書を眺める(2020年7月)
このリビジョンでの変更は、t[a][b]
のような構文をt[a, b]
と書き換えてoperator[]
に委譲する機能についての議論を追加した事です。ただし、これはここでは提案されていません。
P2162R2 Inheriting from std::variant (resolving LWG3052)
std::variant
を公開継承している型に対してもstd::visit()
できるようにする提案。
以前の記事を参照 - P2162R0 Inheriting from std::variant (resolving LWG3052) - [C++]WG21月次提案文書を眺める(2020年5月) - P2162R1 Inheriting from std::variant (resolving LWG3052) - [C++]WG21月次提案文書を眺める(2020年8月)
このリビジョンでの変更は、文言の調整のみです。
この提案は2021年2月22日(米国時間)に行われた全体会議でC++23入りが承認されています。次のワーキングドラフトからC++23に反映されます。
P2164R4 views::enumerate
元のシーケンスの各要素にインデックスを紐付けた要素からなる新しいシーケンスを作成するRangeアダプタviews::enumrate
の提案。
以前の記事を参照
- P2164R0 views::enumerate - [C++]WG21月次提案文書を眺める(2020年5月)
- P2164R1 views::enumerate - [C++]WG21月次提案文書を眺める(2020年6月)
- P2164R2 views::enumerate - [C++]WG21月次提案文書を眺める(2020年9月)
- P2164R3 views::enumerate - [C++]WG21月次提案文書を眺める(2020年11月)
このリビジョンでの変更は、views::enumrate
の間接参照結果の型がindex/value
という名前のメンバを持つようにするために必要な事について追記された事です。
以前の提案では結果の型はシンプルな集成体で、views::enumrate
のイテレータのvalue_type
とreference
は同じ型とされていました。
struct result {
count index;
T value;
};
しかし、indirectly_readable
コンセプトを満たすためにはvalue_type
とreference
の間のcommon_reference
が必要であり、そのためにはそこそこ大きな追加の実装が必要となります。
このリビジョンではその実装の一部を示すとともに、std::pair/tuple
を再現せずまた利用せず、かつ名前のついた(説明専用でない)新しい型を導入する方向性を提案しています。
また、以前の提案では上記result
型のメンバはconst
メンバでしたが、LEWGでのレビューで否定されたため、非const
に修正されました。
P2195R2 Electronic Straw Polls
各委員会での投票が必要となる際に、メールまたは電子投票システムを用いて投票できるようにする提案。
以前の記事を参照
- P2186R0 : Removing Garbage Collection Support - [C++]WG21月次提案文書を眺める(2020年7月)
- P2186R1 Removing Garbage Collection Support - [C++]WG21月次提案文書を眺める(2020年12月)
このリビジョンでの変更はよく分かりません。
P2216R3 std::format improvements
std::format
の機能改善の提案。
以前の記事を参照
- P2216R0 : std::format improvements - [C++]WG21月次提案文書を眺める(2020年9月)
- P2216R1 std::format improvements - [C++]WG21月次提案文書を眺める(2020年12月)
- P2216R2 std::format improvements - [C++]WG21月次提案文書を眺める(2021年01月)
このリビジョンでの変更は、提案している文言の調整がメインです。
この提案はすでにC++20に逆適用されることがほぼ決まっています。
P2231R1 Missing constexpr in std::optional and std::variant
std::optional
とstd::variant
をさらにconstexpr
対応させる提案。
以前の記事を参照
このリビジョンでの変更は、機能テストマクロを追加した事です。
この提案はLEWGでのレビューが終わる前にLWGでのレビューが完了しており、C++23に導入するコンセンサスが得られています。LEWGのレビュー完了を待って、全体会議での投票にかけられる予定です。
P2234R1 Consider a UB and IF-NDR Audit
C++標準のUB(undefined behavior)とIF-NDR(ill-formed no diagnostic required)について、委員会の小さなチームによって監査されるプロセスの提案。
以前の記事を参照
このリビジョンでの変更は、R0が何を目的としているか混乱を招いたようで、文書を全体的に再構成した事です。
P2242R1 Non-literal variables (and labels and gotos) in constexpr functions
constexpr
関数において、コンパイル時に評価されなければgoto
やラベル、非リテラル型の変数宣言を許可する提案。
以前の記事を参照
このリビジョンでの変更は、この提案は何かを新しくconstexpr
関数で実行可能にしようとするものではなく、そのことを明記した事です。
この提案はEWGでのレビューでは反対意見なくCWGへ転送されるコンセンサスが得られています。このリビジョンのEWGでの投票を待って、CWGに送られる予定です。
P2249R0 Mixed comparisons for smart pointers
スマートポインターの比較演算子に生ポインタとの直接比較を追加する提案。
スマートポインタ型はリソースの所有権を表現する方法として広く認識されており、対して生ポインタはリソースにアクセスするために用いる所有権を保有しないものとして認識されつつあります。
そして、どちらも任意のリソース(オブジェクト)のアドレスを表現するという意味論を共有しています。
その一方で、現在の標準ライブラリにあるスマートポインタ型の比較演算子は自身と同じ型(テンプレートパラメータを除いて)との間の比較演算子しか備えていません。そのため、生ポインタとスマートポインタの間で比較をするためには、一旦スマートポインタから生ポインタを取り出さなければなりません。
std::shared_ptr<object> sptr1, sptr2; object* rawptr; // 2つのポインタが同じオブジェクトを指しているかを調べる。 if (sptr1 == sptr2) { ... } // OK if (sptr1 == rawptr) { ... } // Error if (sptr1.get() == rawptr) { ... } // OK
この事は同値比較演算子だけではなく、大小比較を行う関係演算子でも同様です。
スマートポインタと生ポインタの比較を行うケースは一般的に発生しているため、スマートポインタに生ポインタとの比較演算子を追加する事でこのような不整合を修正しようとする提案です。
この提案では、std::unique_ptr
とstd::shared_ptr
に対して保持するポインタと比較可能な任意の型との比較を行う==
と<=>
を追加する事で、生ポインタとの比較を実装しています。
// ManagerはObjectを所有し、利用者にはそのポインタを貸し与える // クライアントは特定のObjectについて作業をしてもらうために、借りたポインタをManagerに渡す事で作業を依頼する class Manager { std::vector<std::unique_ptr<Object>> objects; public: // Objectのポインタを取得 Object* get_object(std::size_t index) const { return objects[index].get(); } // 指定したObjectを削除する void drop_object(Object* input) { // 直接比較できないので述語オブジェクトを作成しなければならない auto isEqual = [input](const std::unique_ptr<Object>& o) { return o.get() == input; }; erase_if(objects, input); // この提案の後では、次の1行で事足りる erase(objects, input); } // Objectのインデックスを得る ssize_t index_for_object(Object* input) const { // 先ほどと同じ理由 // このような述語オブジェクトは様々なところで重複して頻出する可能性がある // 一元化すればいいのだが、多くの場合その場で書いてそのままにしがち・・・ auto isEqual = [input](const std::unique_ptr<Object>& o) { return o.get() == input; }; auto it = std::ranges::find_if(objects, isEqual); // etc. // この提案の後では、次の1行で事足りる auto it = std::ranges::find(objects, input); } };
P2280R1 Using unknown references in constant expressions
定数式での参照のコピーを許可する提案。
以前の記事を参照
このリビジョンでの変更は、EWGのレビューと投票の結果を記載した事と、提案する文言を改善した事(特にthis
ポインタの定数式での利用を明示的に許可したこと)です。
P2281R1 Clarifying range adaptor objects
range adaptor objectがその引数を安全に束縛し、自身の値カテゴリに応じて内部状態を適切にコピー/ムーブする事を明確化する提案。
以前の記事を参照
このリビジョンでの変更は、LWGからのフィードバックを提案する文言に反映した事です。
この提案はライブラリのIssue解決の多ものものであるのでLWGからレビューが開始されています。そこではC++23に向けて導入するコンセンサスが得られており、次の全体会議(2021年6月)で採択のための投票にかけられる予定です。
P2286R1 Formatting Ranges
任意の範囲を手軽に出力できる機能を追加する提案。
以前の記事を参照
このリビジョンでの変更は、実装定義としている範囲の出力フォーマットのオプションを提示した事です。何人かの方が筆者の方にフォーマットを実装定義としていることは受け入れられないと伝えているようです。
P2287R1 Designated-initializers for base classes
基底クラスに対して指示付初期化できるようにする提案。
以前の記事を参照
このリビジョンでの変更は、R0で提案していた基底クラスを指定する構文を拡張して、{}
を取り除いた形の基底クラスのメンバを直接指定した初期化を許可するようにしたことです。
struct A { int a; }; struct B : A { int b; }; int main() { // R0で提案した構文 B b1{:A = {.a = 1}, b = 2}; B b2{:A{.a = 1}, b = 2}; B b3{:A{1}, .b{2}}; // R1で追加された形式 B b4{.a = 1, .b = 2}; B b5{.a{1}, .b{2}}; }
P2289R0 2021 Winter Library Evolution Polls
2021年の冬(1月から3月にかけて)に予定されている、LEWGでの全体投票の予定表。
以下の9つの提案が投票にかけられる予定です。
- P0288R7 any_invocable
- P2265R0 Renaming any_invocableによって、
move_only_function
に名前が変更されました。
- P2265R0 Renaming any_invocableによって、
- P1642R5 Freestanding Library: Easy [utilities], [ranges], and [iterators]
- P2216R2 std::format improvements
- P2077R2 Heterogeneous erasure overloads for associative containers
- P2136R2 invoke_r
- P1951R0 Default Arguments for pair's Forwarding Constructor
- P2231R0 Add further constexpr support for optional/variant
- P0901R8 Size feedback in operator new
- P1478R6 Byte-wise atomic memcpy
基本的にはLEWGでの作業を完了してLWG(CWG)へ転送することを確認するための投票です。
P2290R0 Delimited escape sequences
文字・文字列定数中の8進・16進エスケープシーケンスおよびユニバーサル文字名について、その区切りが明確になるような形式を追加する提案。
現在文字列中のエスケープシーケンスには、ユニバーサル文字名(\uxx... or \Uxx...
)、8進エスケープシーケンス(\ooo
)、16進エスケープシーケンス(\xnn...
)の3種類があります。8進エスケープシーケンスは3文字制限がありますが、16進エスケープシーケンスには長さの制限はありません。そして、どちらもエスケープシーケンス中に受け付けられない文字が出てきたらそこでエスケープシーケンスを終了するようになっています。
これによって、次のような問題が発生します。
"\17"; // 8進エスケープシーケンス、"0x0f"と等価 "\18"; // 8進エスケープシーケンスと文字、"0x01 8"の2文字 "\xabc"; // 1文字 "\xab" "c"; // 2文字
つまりどれも、エスケープシーケンスの終端(あるいは区切り)が明確ではありません。一番最後の例の様な回避策はありますが分かりづらく、この問題をよく知らない人から見ると余計なことをしているようにしか見えません。
また、ユニバーサル文字名は16進数字4桁もしくは8桁のどちらかになりますが、ユニコードのコードポイントの範囲が[0, 0x10FFFF]に制限されているため、有効なコードポイントは5桁以下の16進数字列によって書くことができます。そして、5桁のユニコード文字を書く場合は\U0001F1F8
のように冗長な0が必要になってしまいます。
この提案ではこれらの問題の解決のために、\u{}, \o{}, \x{}
の形の新しいエスケープシーケンス構文を提案しています。それぞれ{}
の中に任意の長さの数字列(8 or 16進)を書けること以外は既存の対応するエスケープシーケンスと同様の扱いとなります。そして、この形式のエスケープシーケンスは現在コンパイルエラーとなる(\o
の形式は予約されている)ために既存のコードを壊すこともありません。
なお、エスケープシーケンスの置換は文字列リテラルの連結の前に行われるため、"\x{4" "2}"
のような形での使用はコンパイルエラーとすることを提案しています。
この提案の後では、先程の問題のエスケープシーケンスを次のように書くことができるようになります。
"\o{18}"; // 8進エスケープシーケンスに8は現れてはいけないのでコンパイルエラー "\x{ab}c"; // 2文字 "\u{1F1F8}"; // 5桁のユニバーサル文字名
この提案はC++に対してのものですがCに対しても同じ問題がある事から、WG14(C標準化委員会)に周知のためにSG22にも提出されています。
この部分の9割は以下の方のご指摘により成り立っています。
P2291R0 Add Constexpr Modifiers to Functions to_chars and from_chars for Integral Types in Header
std::to_chars, std::from_chars
を整数変換に関してconstexpr
にする提案。
現在のC++にはコンパイル時に使用可能な文字列と数値の相互変換のためのものはありません。そのため、コンパイル時に文字列変換を行うには在野のライブラリに頼るほかありませんでした。
標準ライブラリには様々な実行時文字列変換法があり、中でもstd::to_chars, std::from_chars
はロケールに依存せず、例外を投げず、動的メモリ確保も行わないなど、コンパイル時の文字列と数値の相互変換に最適な候補です。そのため、この2つの関数を整数変換に限ってconstexpr
対応することを目指す提案です。
constexpr std::optional<int> to_int(std::string_view s) { int value; if (auto [p, err] = std::from_chars(s.begin(), s.end(), value); err == std::errc{}) { return value; } else { return std::nullopt; } } static_assert(to_int("42") == 42); static_assert(to_int("foo") == std::nullopt);
C++20でstd::string
がコンパイル時に構築できるようになったため、この提案と合わせるとstd::format
をcosntexpr
にすることができるようになります。
筆者の方は、MSVC STLの実装をconstexpr
対応させることで実装テストを行い、その結果大きな変更や問題がなかったことを確認しています。
浮動小数点数変換のconstexpr
対応を提案していないのは、実装が難しいためにサポートが進んでおらず(MSVCとGCC11が実装完了)、提案するのは時期尚早という判断のようです。
P2295R0 Correct UTF-8 handling during phase 1 of translation
C++コンパイラが少なくともUTF-8をサポートするようにする提案。
現在のC++コンパイラが入力ソースファイルのエンコードとしてサポートしている文字コード(ソースファイル文字集合)は実装定義であり、必ずしもUTF-8をサポートしていません。それによって、UTF=8ソースファイルで書かれたmain
関数だけのシンプルなプログラムですら、移植性を保証できません。
C++コンパイラがどのような文字コードを入力としてサポートするにせよUTF-8はサポートすることを義務付けることで、ソースコード移植性の問題を改善し、またユニコード関連の機能やその処理方法を(規格中でも)適切に指定し、幅広く使用できるようにしようとする提案です。
現在の主要な実装は全て、細部の差異はあれどUTF-8をサポートしているため、この提案の実装に必要なのはそれをデフォルトにすることだけです。この提案は、ユーザーのUTF-8ソースコードが適切にでコードされていることを保証する一方で、実装者はより寛大なオプションを提供できるようにするものです。例えば、UTF-8ソースファイルであることをどう決定するか(BOMの考慮)や、UTF-8として無効なコードポイントのシーケンスをどう扱うかなどは実装定義となります。
P2297R0 Wording improvements for encodings and character sets
規格の文章の~ encodingと~ character setという言葉の使い方を改善し、何が何を指しているのかを一貫させる提案。
これによって、ユニバーサル文字名の扱いに関する3件のIssueが解決されます。
- CWG Issue 1403. Universal-character-names in comments
- CWG Issue 578. Phase 1 replacement of characters with universal-character-names
- CWG Issue 1335. Stringizing, extended characters, and universal-character-names
- P2295 進行状況
P2301R0 Add a pmr alias for std::stacktrace
std::basic_stacktrace
のstd::pmr
エイリアス(std::polymorphic_allocator
を用いるエイリアス)を追加する提案。
std::basic_stacktrace
はテンプレートパラメータにアロケータ型を取り、std::allocator
があてがわれたエイリアスがstd::stacktrace
として定義されています。そして、std::stacktrace
はAllocatorAwareContainerの要件を満たしており、std::polymorphic_allocator
を用いることに障害はありません。
他のコンテナなど、アロケータモデルをサポートしデフォルトでstd::allocator
を使用するものについてstd::pmr
エイリアスが用意されているように、std::basic_stacktrace
にもstd::pmr::stacktrace
を用意すべき、という提案です。
P2302R0 Prefer std::ranges::contains over std::basic_string_view::contains
新しいアルゴリズムとしてstd::ranges::contains
を追加して、std::basic_string_view/std::basic_string
の.contains()
メンバ関数を削除する提案。
C++23に向けたP1679R3の採択によって、std::string/string_view
にはある文字列が含まれているかを判定するための.contains()
メンバ関数を備えています。
筆者の方は、このような操作の必要性は同意するがこの操作はより一般の範囲(range)に適用可能なアルゴリズムであり、メンバ関数ではなく<algorithm>
に配置される非メンバアルゴリズムとして追加すべき、と述べています。
それによって、ある範囲に別の範囲が含まれているかどうか、あるいは述語を満たす部分が含まれているかどうかを調べる形に一般化でき、また他のrangeアルゴリズムに従った形で幅広い型について利用できるようになります.
std::ranges::contains
の使用イメージ。
// 文字の範囲と文字を受ける if (std::ranges::contains(haystack, 'o')) { // meow } // 文字範囲のイテレータペアと文字を受ける if (std::ranges::contains(haystack.begin(), haystack.end(), 'c')) { // purr } // 探索する範囲のイテレータペアと探索したい範囲のイテレータペアを受ける if (std::ranges::contains(haystack.begin(), haystack.end(), long_needle.begin(), long_needle.end())) { // hiss } // 探索する範囲と探索したい範囲を受ける if (std::ranges::contains(haystack, long_needle)) { // hiss again } // 探索する範囲と述語を受ける if (std::ranges::contains(haystack, long_needle, bind_back(std::modulo(), 4))) { // double purr }
P2314R0 Character sets and encodings
規格文書中の ~ character setという言葉を明確に定義し直す提案。
- translation character set
- basic character set
- basic literal character set
- ordinary / wide literal encoding
そしてこれらの用語を用いて文言を書き直すことで、翻訳フェーズ1でユニバーサル文字名が形成されなくなり、全てのユニコード文字入力はコンパイル全体で保持されるようになります。それにより、プリプロセッサにおける文字列化演算子(#
)の動作が変更されます。
C++20 | この提案 |
---|---|
#define S(x) # x const char * s1 = S(Kテカppe); // "K\\u00f6ppe" const char * s2 = S(K\u00f6ppe); // "K\\u00f6ppe" |
#define S(x) # x const char * s1 = S(Kテカppe); // "Kテカppe" const char * s2 = S(K\u00f6ppe); // "Kテカppe" |
ただし、既存の実装は全てこれを実装している(エスケープされたユニバーサル文字名を返す実装はない)ために問題にはならないようです。
また、これらの変更によって現在使用されているbasic / extended source character setという言葉は使われなくなります。
P2315R0 C++ Standard Library Issues to be moved in Virtual Plenary, Feb. 2021
標準ライブラリのIsuueのうち2021年02月のオンライン全体会議の際に投票にかけられるもののリスト。
ここにあるものは投票でコンセンサスが得られればLWG Isuueとして規格に反映されることになります。
これを書いている時点で投票は完了しており、その結果ここに記載されているIssueは全て標準に適用されることになりました。
P2316R0 Consistent character literal encoding
#if
プリプロセッシングディレクティブの条件式において、文字リテラルをC++の式の意味論と同等に扱えるようにする提案。
#if 'A' == '\x41' //... #endif if ('A' == 0x41){}
現在の仕様では、この2つの条件式は同じ結果となる保証がありません。
#if
の条件式において文字リテラルは対応する数値に変換され処理されますが、文字リテラルをどのように解釈するか(どのエンコーディングで読み取るか)は実装定義であり、C++の式上でのそれと一致するかどうかも実装定義とされます。
筆者の方がvcpkgを用いてコードベースを調査したところ、このような#if
での文字リテラルの比較はその環境でのナロー文字エンコーディングを取得するために使用されているようです。
sqliteより
#if 'A' == '\301' # define SQLITE_EBCDIC 1 #else # define SQLITE_ASCII 1 #endif
主要なコンパイラは全て期待通りに動作し、#if
での文字リテラルをナロー文字エンコーディングにおいて対応する数値として扱うようです。
C++で文字エンコーディングを検出するより良い方法は提案中ですが現状では手段がなく、この振る舞いを標準化して上記の様なコードがユーザーの期待通りに振舞うことを保証しようとする提案です。
P2317R0 C++ - An Invisible foundation of everything
C++とは何か?(原則と理想や使用についてなど)というよく聞かれる質問に対する返答をまとめた文書。
Bjarne Stroustrup先生がC++とは何か?とかC++はまだどこでも使われてるの?などよく聞かれるらしく、その簡単な答えとその詳細を知ることのできる文書へのリンクをまとめた文書です。WG21メンバーに向けて書かれたものではないですが、WG21メンバにも役立つ可能性があるためWG21に提出された様です。
目次
- 目的と手段
- C++の設計の高レベルでの目的とシステムにおけるその役割
- 使用
- 基礎的な使用法に焦点を当てた、C++のいくつかの用例
- 進化
- フィードバックに基づくC++開発のための進化戦略
- 保証、言語、ガイドライン
- 進化、安定性、表現力、型・リソース安全を同時に達成するための戦略
- 人
- ソフトウェア開発における人の役割の再認識
- 参考文献とリソース
- C++のより深い理解につながる可能性のある参考文献への注釈付きリスト
- 付録
- C++の主要なプロパティと機能の非常に簡単な概説
C++ヲタク必見です!
P2320R0 The Syntax of Static Reflection
静的リフレクションのための新しい構文の提案。
表現力・読みやすさ・柔軟さ・曖昧さがない・実装可能、の観点から提案中のものも含めた現在のリフレクションの構文を見直したものの提案です。
リフレクション
現在のリフレクションTSでは、名前からメタ情報を取得するのにreflexpr()
という構文を使用しています。この提案では代わりに^
を使用します。
// この提案 meta::info r1 = ˆint; // reflects the type-id int meta::info r2 = ˆx; // reflects the id-expression x meta::info r3 = ˆf(x); // reflects the call f(x) // N4856現在 meta::info r1 = reflexpr(int); // reflects the type-id int meta::info r2 = reflexpr(x); // reflects the id-expression x meta::info r3 = reflexpr(f(x)); // reflects the call f(x)
スプライシング
リフレクションによって取得したメタ情報から型名を取り出して利用することです。この提案では[: R :]
の様な構文によって行います。
struct S { struct Inner { }; }; template<int N> struct X; auto refl = ˆS; auto tmpl = ˆX; void f() { typename [:refl:] * x; // OK: xはS* [:refl:] * x; // error: typename必須 [:refl:]::Inner i; // OK typename [:refl:]{}; // OK: Sの一時オブジェクトをデフォルト構築 using T = [:refl:]; // OK struct C : [:refl:] {}; // OK template [:tmpl:]<0>; // OK [:tmpl:] < 0 > x; // error: xと0の比較になる // N4856現在 namespace reflect = std::experimental::reflect; using refl_t = reflexpr(S); using tmpl_t = reflexpr(X); reflect::get_reflected_type_t<refl_t> * x; typename reflect::get_reflected_type_t<refl_t>::Inner i; reflect::get_reflected_type_t<refl_t>{}; using T = reflect::get_reflected_type_t<refl_t>; struct C : reflect::get_reflected_type_t<refl_t> {}; // 残りの2例は対応するものがない(おそらく) }
パックのスプライシング
リフレクションによって取得したメタ情報から型名のリストを取り出して利用することです。この提案では...[: R :]...
の様な構文によって行います。
// 型エイリアス using T = std::tuple<int, ...[:range_of_types:]..., bool>; // 関数宣言 void f(... [:range_of_types:] ...args); // 関数呼び出し fn(0, 1, ...[:range:]...); // OK: 通常引数(0, 1)の後に展開 fn(...[:range:]..., 0, 1); // OK: 通常引数(0, 1)の前に展開 fn(...[:range:] * 2...); // OK: rangeの要素に2をかけながら展開 fn(...[:r1:] * [:r2:]...); // OK: ただし、r1とr2の長さは同じでなければならない
P2321R0 zip
<ranges>
にzip_view, adjacent_view, zip_transform_view, adjacent_transform_view
を追加する提案。
これら4つのzip
likeなview
は基本的には複数の範囲を一つの範囲に変換する様に振る舞うものです。そのため、元のそれぞれの範囲の要素型(value_type
)をEn
とすると、間接参照の結果型(reference
)はstd::pair<E1&, E2&>
やstd::tuple<E1&, ..., En&>
の様になるでしょう。
このstd::pair
とstd::tuple
がイテレータの間接参照の結果として返されるプロクシオブジェクトとして使用されるのに必要な性質を備えておらず、その議論が間に合わなかったためにC++20ではこれらのview
は採択されませんでした。
この提案は、std::pair
とstd::tuple
の各種の問題を解決した上で、zip_view, adjacent_view, zip_transform_view, adjacent_transform_view
を追加するものです。
std:tuple
への出力
std::indirectly_writable
コンセプトは、const_cast
を用いた制約式によって、イテレータの間接参照がprvalueを返すようなイテレータを弾く一方で、それが単にプロクシ参照である場合は許容する、という事をしています。これはstd::output_iterator
コンセプトを構成するものの一つです。
zip
likeなview
のイテレータはその間接参照の結果としてstd::pair/tuple
のprvalueを返します。output_iterator
として有効であるためには、それをconst
化したもの(例えば、const std::tuple<...>&&
なオブジェクト)に対して代入できなければなりません。
当然ながら、現在のstd::pair/tuple
はそうなっておらず、プロクシイテレータの間接参照の結果型としては不足しています。
この提案では、std::pair/tuple
に代入演算子のconst
オーバーロードを追加し、std::pair/tuple
がconst
でもその要素に代入が可能であるならばできるように変更します。
同時に、std::vector<bool>::reference
にも同様の理由から同じように代入演算子のconst
オーバーロードを追加します。
std:tuple
の読み取り
std::indirectly_readable
コンセプトは、イテレータ型のvalue_type&
とreference
の間にcommon_reference
が存在していることを求めています。これはstd::input_iterator
コンセプトを構成するものの一つです。
zip
likeなview
のイテレータにおけるvalue_type&
とreference
の間のcommon_reference
とは何でしょうか?
std::vector<int> vi = /* ... */; std::vector<std::string> vs = /* ... */; ranges::sort(views::zip(vi, vs));
例えばこの場合のzip_view
のイテレータのvalue_type
はstd::pair<int, std::string>
、reference
はstd::pair<int&, std::string&>
となります。
std::pair<int&, std::string&>
はstd::pair<int, std::string>
へは変換できるため、common_reference
はstd::pair<int, std::string>
となるでしょうか。参照ではありませんが、common_reference
に求められることは果たします。
しかし、zip
対象のイテレータの要素型がコピー不可能な型になった場合、value_type
とreference
はどちらをどちらにも変換できなくなるため、common_reference
は機能しなくなります。それによって、input_iterator
のモデルとなれなくなります。
この事はstd::tuple
にも同じことが言えます。
この問題の解決のために、std::pair<T1, T2>
に対してstd::pair<U1, U2>&, const std::pair<U1, U2>&&
から構築するコンストラクタ、およびstd::tuple<Ts...>
に対してstd::tuple<Us...>&, const std::pair<Us...>&&
から構築するコンストラクタを追加します。
この2つのコンストラクタを追加するだけで、std::pair<std::unique_ptr<int>, std::string>
からstd::pair<std::unique_ptr<int>&, std::string&>
が構築できるようになります。そして、この型は参照のセマンティクスを持っています(std::tuple
でも同様)。
またcommon_reference
に適合するために、std::tuple
とstd::pair
に対してstd::basic_common_reference
とstd::common_type
の特殊化を追加します
これは、common_reference
としてよりふさわしい型となります。
zip, zip_tranform
のvalue_type
zip_transform
は与えられた範囲をどのように一つの範囲にzip
するかを指定することのできるview
です。zip
はデフォルトでstd::tuple/pair
を用いてまとめ、その振る舞いを変更できません。対して、zip_transform
はその部分を任意の関数を指定することでカスタマイズできます。
ここで問題になるのが、zip_transform
のvalue_type
がどうなるかという点です。
std::vector<int> vi = /* ... */; std::vector<std::string> vs = /* ... */; auto b = views::zip_transform([](auto&... r){ return std::tie(r...); }, vi, vs);
このzip_transform
はzip
と同じことをします。b
のreference
はstd::tuple<int&, std::string&>
となり、これはzip
のふるまいと一貫しています。しかし、この場合のvalue_type
をstd::tuple<int, std::string>
としてしまう事は適切でしょうか?
zip
の行う事と異なり、この場合にtuple
の各要素が参照となっているのはユーザーが指定した変換の結果であり、別の変換ではこれは参照とならないかもしれません。従って、zip_transform
のvalue_type
は単にstd::remove_cvref_t<std::invoke_result_t<F&, std::range_reference_t<R>...>>
のような型とするのが適切です。上記の例ではstd::tuple<int&, std::string&>
となります。ただ、そうしてしまうとzip
との振る舞いの一貫性がなくなってしまいます。
この提案ではこの方針を採用し、zip
とzip_transform
のreference/value_type
の間の一貫性を失う事を許容することにしたようです。
これらの様な設計を選択し、C++23への導入に向けてzip
likeな4つのview
の作業が開始されます。
なお、adjacent_view
とは1つの範囲のある要素についてそれに続くN - 1
要素をひとまとめにしたものを要素とする範囲を生成するview
で、入力の範囲に対してその範囲の1つ目の要素を飛ばした範囲を生成して、その二つの範囲をzip
したようなview
です。adjacent_transform_view
はadjacent
する部分をカスタムできるものです。
std::vector<int> vi = {1, 2, 3, 4}; std::vector<std::string> vs = { "one", "two", "three", "four" }; for (auto& [n, s] : vi | std::views::zip(vs)) { std::cout << n << " : " << s << std::endl; } // 1 : one // 2 : two // 3 : three // 4 : four for (auto [n, m] : vi | std::views::adjacent<2>) { std::cout << n << " : " << m << std::endl; } // 1 : 2 // 2 : 3 // 3 : 4
P2322R0 ranges::fold
range
アルゴリズムであるranges::fold
の提案。
このranges::fold
というのは関数型言語でfoldl
と呼ばれているものに対応し、現在のC++標準ライブラリには数値に特化したイテレータ版として<numeric>
にstd::accumulate
として存在しています。
std::ranges::accumlate
もP1813R0で提案されており、検討中のstd::ranges::accumlate
は以下のようになっています。
template <input_range R, movable T, class Proj = identity, indirect_magma<const T*, projected<iterator_t<R>, Proj>, T*> BOp = ranges::plus> constexpr accumulate_result<safe_iterator_t<R>, T> accumulate(R&& r, T init, BOp bop = {}, Proj proj = {});
これを良しとしないのは、特定の2項演算をデフォルトにするべきではない、戻り値型が複雑(単に結果だけが欲しい)、制約がきつすぎる(indirect_magma
コンセプトは大きすぎる)、等の理由です。
この操作は数値に限定されたものではないためより一般的な名前を付けて、より汎用的であるために過度な制約を課さないようにしたものがranges::fold
であり、もはや数値のためのものではないため<algorithm>
に追加することを提案しています。
提案ではさらに、ranges::fold
のファミリとして、foldr
に対応するranges::fold_right
と、範囲の最初の要素を初項として使用するranges::fold
であるranges::fold_first
、最後の要素を初項として使用するranges::fold_right
であるranges::fold_right_last
を同時に提案しています。
std::vector<int> vec = {1, 2, 3, 4, 5}; int sum1 = std::ranges::fold(vec, 0, std::ranges::plus{}); int sum2 = std::ranges::fold_first(vec, std::ranges::plus{}); // sum1 == sum2 == 15 std::vector<std::string> vec2 = {"aaa", "bbb", "ccc"}; std::string concat1 = std::ranges::fold_first(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_last(vec2, std::ranges::plus{}); // concat2 == concat3 == "cccbbbaaa"
P2324R0 Labels at the end of compound statements (C compatibility)
複合ステートメント(compound statement)の末尾にラベルを置けるようにする提案。
Cではこれが可能になっていますがC++では可能になっておらず、Cとの互換性向上のためにできるようにしようという提案です。この提案はSG22に提出されたものです。
複合ステートメントとはブロック({...}
)のことで、その末尾とは例えば関数の末尾の事です。
void foo(void) { first: // C/C++共にok int x; second: // C/C++共にok x = 1; last: // Cはok、C++はng }
この提案はこの例のlast
の様なラベルを置けるようにするものです。
P2325R0 Views should not be required to be default constructible
Viewとみなされる型にデフォルト構築可能性を要求しない様にする提案。
Viewを定義しているstd::ranges::view
コンセプトは、現在次の様に定義されています。
template <class T> concept view = range<T> && movable<T> && default_initializable<T> && enable_view<T>;
view
はrange
であって少なくともムーブ可能である必要があり、view
は構文的な部分よりも意味論の部分でrange
と大きく異なるため、構文的にview
であるかどうかは明示的なオプトイン(enable_view
)が必要です。
ただ、残ったdefault_initializable
に関しては、C++20の<ranges>
に至る議論からはview
がデフォルト構築可能である事のモチベーションは見つからず、range-v3のものを含めても本質的にデフォルトコンストラクタを必要とするview
はむしろ少数であり、default_initializable
の要求はview
には不要のものに思えます。
また、デフォルト構築を要求されていることによって、関数を受け取るタイプのview
(range adaptor)は受け取った関数オブジェクトをstd::optional
(semiregular-box)に格納する必要があるため、実装を複雑化しview
のサイズを増加させています。
さらに、型がデフォルト構築可能であるという性質を持つことによって、そのような型をメンバとして持つクラスには、そのメンバが初期化されていないという追加の状態が発生します。それによって、ユーザーはそれをチェックする必要があり、またドキュメントなどにはその旨を記載する必要が出てきます。これは、現在のview
に当てはまっていることです。
デフォルト構築可能という要求がメリットをもたらさずむしろ害(型に無効状態を追加し、全てのrange adaptorにそのサイズ増加をもたらし、これが原因でview
コンセプトを満たせない場合のユーザの混乱など)をもたらすのであれば、それは取り除くべき、という提案です。
この提案では、view
コンセプトからdefault_initializable
を取り除くと共に、weakly_incrementable
コンセプトからも取り除くことで、input iterator/output iterator
へのデフォルト構築可能という要求を取り除くことを提案しています。
そして、一部のview
およびイテレータ型からデフォルトコンストラクタを削除し、std::span
が常にview
となるようにします。
次
多分2週間後くらい