文書の一覧
全部で164本あります。
もくじ
- N5004 2025 Sofia Meeting Invitation and Information
- N5005 WG21 2025-01 Hagenberg Admin telecon minutes
- N5006 2025 WG21 admin telecon meetings (revised 2025-02-20)
- N5007 WG21 02/2025 Hagenberg Minutes of Meeting
- N5008 Working Draft, Programming Languages -- C++
- N5009 Editors' Report, Programming Languages -- C++
- P0260R15 C++ Concurrent Queues
- P0260R16 C++ Concurrent Queues
- P0876R20 fiber_context - fibers without scheduler
- P1494R5 Partial program correctness
- P1967R14 #embed - a simple, scannable preprocessor-based resource acquisition method
- P2079R7 Parallel scheduler
- P2287R4 Designated-initializers for base classes
- P2414R6 Pointer lifetime-end zap proposed solutions
- P2663R7 Proposal to support interleaved complex values in std::simd
- P2719R4 Type-aware allocation and deallocation functions
- P2758R5 Emitting messages at compile time
- P2781R6 std::constexpr_wrapper
- P2781R7 std::constexpr_wrapper
- P2781R8 std::constexpr_wrapper
- P2786R12 Trivial Relocatability For C++26
- P2786R13 Trivial Relocatability For C++26
- P2825R5 Overload resolution hook: declcall( unevaluated-call-expression )
- P2830R10 Standardized Constexpr Type Ordering
- P2841R7 Concept and variable-template template-parameters
- P2843R2 Preprocessing is never undefined
- P2846R6 reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges
- P2863R9 Review Annex D for C++26
- P2873R3 Remove Deprecated locale category facets for Unicode from C++26
- P2876R2 Proposal to extend std::simd with more constructors and accessors
- P2899R1 Contracts for C++ - Rationale
- P2900R14 Contracts for C++
- P2933R4 Extend header function with overloads for std::simd
- P2988R10 std::optional<T&>
- P2988R11 std::optional<T&>
- P2996R10 Reflection for C++26
- P3008R4 Atomic floating-point min/max
- P3016R6 Resolve inconsistencies in begin/end for valarray and braced initializer lists
- P3019R13 Vocabulary Types for Composite Class Design
- P3019R14 Vocabulary Types for Composite Class Design
- P3060R2 Add std::views::indices(n)
- P3070R3 Formatting enums
- P3074R6 trivial unions (was std::uninitialized)
- P3074R7 trivial unions (was std::uninitialized)
- P3081R2 Core safety profiles for C++26
- P3096R6 Function Parameter Reflection in Reflection for C++26
- P3096R7 Function Parameter Reflection in Reflection for C++26
- P3104R3 Bit permutations
- P3111R4 Atomic Reduction Operations
- P3111R5 Atomic Reduction Operations
- P3137R3 views::to_input
- P3149R9 async_scope -- Creating scopes for non-sequential concurrency
- P3161R3 Unified integer overflow arithmetic
- P3179R6 C++ parallel range algorithms
- P3179R7 C++ parallel range algorithms
- P3229R1 Making erroneous behaviour compatible with Contracts
- P3230R2 views::unchecked_(take|drop)
- P3242R1 Copy and fill for mdspan
- P3248R3 Require [u]intptr_t
- P3284R3 write_env and unstoppable Sender Adaptors
- P3287R3 Exploration of namespaces for std::simd
- P3296R4 let_async_scope
- P3319R3 Add an iota object for simd (and more)
- P3319R4 Add an iota object for simd (and more)
- P3319R5 Add an iota object for simd (and more)
- P3331R1 Accessing The First and Last Elements in Associative Containers
- P3349R1 Converting contiguous iterators to pointers
- P3365R1 Remove the Deprecated iterator Class Template from C++26
- P3366R1 Remove Deprecated Atomic Initialization API from C++26
- P3367R4 constexpr coroutines
- P3372R3 constexpr containers and adapters
- P3378R2 constexpr exception types
- P3383R2 mdspan.at()
- P3385R4 Attributes reflection
- P3394R2 Annotations for Reflection
- P3395R1 Fix encoding issues and add a formatter for std::error_code
- P3395R2 Fix encoding issues and add a formatter for std::error_code
- P3400R1 Specifying Contract Assertion Properties with Labels
- P3417R1 Handling exceptions thrown from contract predicates
- P3430R3 simd issues: explicit, unsequenced, identity-element position, and members of disabled simd
- P3441R1 Rename simd_split to simd_chunk
- P3441R2 Rename simd_split to simd_chunk
- P3442R1 [[invalidate_dereferencing]] attribute
- P3471R3 Standard Library Hardening
- P3471R4 Standard Library Hardening
- P3472R1 Make fiber_context::can_resume() const
- P3475R2 Defang and deprecate memory_order::consume
- P3477R3 There are exactly 8 bits in a byte
- P3477R4 There are exactly 8 bits in a byte
- P3477R5 There are exactly 8 bits in a byte
- P3480R4 std::simd is a range
- P3481R2 std::execution::bulk() issues
- P3482R1 Design for C++ networking based on IETF TAPS
- P3491R2 define_static_{string,object,array}
- P3492R1 Sized deallocation for placement new
- P3492R2 Sized deallocation for placement new
- P3499R1 Exploring strict contract predicates
- P3500R1 Are Contracts "safe"?
- P3503R1 Make type-erased allocator use in promise and packaged_task consistent
- P3503R2 Make type-erased allocator use in promise and packaged_task consistent
- P3505R0 Fix the default floating-point representation in std::format
- P3516R1 Uninitialized algorithms for relocation
- P3526R0 Container truncation
- P3533R2 constexpr virtual inheritance
- P3537R1 Presentation on Concurrent Queue API
- P3540R1 #embed Parameter offset
- P3544R0 ranges::to<view>
- P3547R1 Modeling Access Control With Reflection
- P3552R1 Add a Coroutine Task Type
- P3556R0 Input files are source files
- P3557R1 High-Quality Sender Diagnostics with Constexpr Exceptions
- P3558R1 Core Language Contracts By Default
- P3561R1 Index based coproduct operations on variant, and library wording
- P3568R1 break label; and continue label;
- P3570R0 optional variants in sender/receiver
- P3579R1 Fix matching of non-type template parameters when matching template template parameters
- P3589R1 C++ Profiles: The Framework
- P3591R0 Contextualizing Contracts Concerns
- P3592R0 Resolving Concerns with const-ification
- P3599R0 Initial Implicit Contract Assertions
- P3603R0 Consteval-only Values and Consteval Variables
- P3605R0 isqrt: A function to calculate integer square root of the nonnegative integer
- P3606R0 On Overload Resolution, Exact Matches and Clever Implementations
- P3608R0 Contracts and profiles: what can we reasonably ship in C++26
- P3611R0 Dealing with pointer errors: Separating static and dynamic checking
- P3613R0 On the beating of horses, and other matters
- P3614R0 Do not remove nor postpone access_context::unchecked
- P3615R0 C++ Standard Library Ready Issues to be moved in Hagenberg, Feb. 2025
- P3616R0 Remove contracts on virtual functions for now
- P3618R0 Allow attaching main to the global module
- P3619R0 Counter-examples for P2688R5
- P3619R1 Counter-examples for P2688R5
- P3620R0 Concerns with the proposed addition of fibers to C++ 26
- P3623R0 Add noexcept to [iterator.range] (LWG 3537)
- P3625R0 either neither
- P3626R0 Make predicate exceptions propagate by default
- P3627R0 Easy-to-adopt security profiles for preventing RCE (remote code execution) in existing C++ code
- P3628R0 break label; and continue label;, tl; dr
- P3630R0 Slides for P3568R0
- P3632R0 P3564R0: Make the concurrent forward progress guarantee usable in bulk
- P3632R1 P3564R0: Make the concurrent forward progress guarantee usable in bulk
- P3633R0 A Byte is a Byte
- P3635R0 We shouldn't rush to require either CHAR_BIT==8 or (u)intNN_t
- P3636R0 LEWG Hagenberg presentation for P3581 No, inplace_vector shouldn't have an Allocator
- P3637R0 Inherit std::meta::exception from std::exception
- P3638R0 Core Language Working Group "ready" Issues for the February, 2025 meeting
- P3639R0 The _BitInt Debate
- P3640R0 Make contracts reliable by default
- P3641R0 Rename std::observable to std::observable_checkpoint, and add a feature-test macro
- P3642R0 Carry-less product: std::clmul
- P3643R0 std::to_signed and std::to_unsigned
- P3650R0 21st Century C++
- P3651R0 Note to the C++ standards committee members
- P3652R0 Constexpr floating-point functions
- P3654R0 Slides for P3516
- P3655R0 zstring_view
- P3656R0 Initial draft proposal for core language UB white paper: Process and major work items
- P3657R0 A Grammar for Whitespace Characters
- P3658R0 Adjust identifier following new Unicode recommendations
- P3660R0 Improve reference_wrapper Ergonomics
- P3661R0 Attributes, annotations, labels
- P3662R0 Improve Increment and Decrement Operator Syntax
- P3663R0 Future-proof submdspan-mapping?
- P3664R0 Make variant_size SFINAE friendly
- おわり
N5004 2025 Sofia Meeting Invitation and Information
2025年6月にブルガリアのソフィアで行われる全体会議のインフォメーション。
予定(2025年6月16日~21日)と場所、ホテルの案内などが記載されています。
N5005 WG21 2025-01 Hagenberg Admin telecon minutes
2025年1月27日に行われた、WG21管理者ミーティングの議事録。
前回からどのような活動があったかや、Hagenberg会議で何をするかなどの報告がなされています。
N5006 2025 WG21 admin telecon meetings (revised 2025-02-20)
今後のWG21管理者ミーティングのインフォメーション。
N5007 WG21 02/2025 Hagenberg Minutes of Meeting
2025年2月にHagenbergで行われた全体会議の議事録。
最終日に行われた全体会議での各グループの作業報告と、全体投票の様子が記録されています。
N5008 Working Draft, Programming Languages -- C++
N5009 Editors' Report, Programming Languages -- C++
↑の変更点をまとめた文書。
P0260R15 C++ Concurrent Queues
↓
P0260R16 C++ Concurrent Queues
標準ライブラリに並行キューを追加するための設計を練る提案。
以前の記事を参照
- P0260R5 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2023年01月)
- P0260R7 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2023年07月)
- P0260R8 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2024年04月)
- P0260R9 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2024年05月)
- P0260R10 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2024年07月)
- P0260R11 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2024年10月)
- P0260R13 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2024年12月)
- P0260R14 C++ Concurrent Queues - [C++]WG21月次提案文書を眺める(2025年01月)
R14での変更は
- 提案されている文言についてより導入的な説明を追記
async_pushとasync_popのset_errorを反映するように、例と設計セクションを更新- より一般的な根拠を追加
- ストップトークンに関する文言を追加
- LEWGの可能な投票項目を追加
pop()に関する文言の修正pop()のstrongly happens beforeを削除busy_asyncを追加- P3570から
get_await_completion_adapter_tを追加し、error-as-optionalを使用してasync_popからのコルーチンに対してoptional<T>を返すようにした error-as-boolを追加しasync_pushからのコルーチンでboolを返す
このリビジョンでの変更は
- 例外サポートヘルパを削除
- 議論のポイントとLEWGの可能な投票リストを削除
try_popの出力引数を削除し、expectedを返すようにしたexpectedに関する議論をhistoric contentsに移動- sequential consistencyのためにorder Qを導入
popによって呼び出されたコンストラクタが例外を送出した場合、キューから値が削除されることを明確にする文言を追加- レビューが必要な文言リストを追加
などです。
P0876R20 fiber_context - fibers without scheduler
スタックフルコルーチンのためのコンテキストスイッチを担うクラス、fiber_contextの提案。
以前の記事を参照
- P0876R11
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2022年10月) - P0876R12
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2023年02月) - P0876R13
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2023年04月) - P0876R14
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2023年10月) - P0876R15
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2024年02月) - P0876R16
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2024年04月) - P0876R17
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2024年07月) - P0876R18
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2024年10月) - P0876R19
fiber_context- fibers without scheduler - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- ファイバーごとの例外状態の実装可能性に関する情報を追加
- St. Louis 2024 EWG notes, Wrocław 2024 EWG notes および Microsoftの実装可能性に関するメールへのリンクを追加
- P3620R0に関する議論を追加
- P3367R3の
constexprコルーチンについて言及
などです。
P1494R5 Partial program correctness
因果関係を逆転するような過度な最適化を防止するためのバリアであるstd::observable()の提案。
以前の記事を参照
- P1494R2 Partial program correctness - WG21月次提案文書を眺める(2021年11月)
- P1494R3 Partial program correctness - WG21月次提案文書を眺める(2024年05月)
- P1494R4 Partial program correctness - WG21月次提案文書を眺める(2024年10月)
このリビジョンでの変更は
- N5001へリベース
<utility>へ移動- より多くのI/Oケースをカバーできるように文言を拡張
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P1967R14 #embed - a simple, scannable preprocessor-based resource acquisition method
コンパイル時(プリプロセス時)にバイナリデータをインクルードするためのプリプロセッシングディレクティブ#embedの提案。
以前の記事を参照
- P1967R3
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2021年04月) - P1967R4
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2021年06月) - P1967R5
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2022年04月) - P1967R6
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2022年05月) - P1967R7
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2022年06月) - P1967R8
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2022年07月) - P1967R9
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2022年10月) - P1967R10
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2023年01月) - P1967R11
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2023年08月) - P1967R12
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2023年12月) - P1967R13
#embed- a simple, scannable preprocessor-based resource acquisition method - [C++]WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は
- 文言の改善
- 引数リストだけではなく、
#embed以降のすべての要素でマクロ展開を考慮するように変更
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2079R7 Parallel scheduler
ハードウェアの提供するコア数(スレッド数)に合わせた固定サイズのスレッドプールを提供するSchedulerの提案。
- P2079R1 Parallel Executor - [C++]WG21月次提案文書を眺める(2020年8月)
- P2079R2 System execution context - [C++]WG21月次提案文書を眺める(2022年1月)
- P2079R3 System execution context - [C++]WG21月次提案文書を眺める(2022年07月)
- P2079R4 System execution context - [C++]WG21月次提案文書を眺める(2024年05月)
- P2079R5 System execution context - [C++]WG21月次提案文書を眺める(2024年10月)
- P2079R6 System execution context - [C++]WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- "System execution context"から"Parallel scheduler"へ変更
- 実行時の置換可能性を削除
- 置換可能性に関するAPIをP3481R1と整合するように調整
bulk_chunkedとbulk_unchunkedをサポート
などです。
P2287R4 Designated-initializers for base classes
基底クラスに対して指示付初期化できるようにする提案。
以前の記事を参照
- P2287R0 Designated-initializers for base classes - [C++]WG21月次提案文書を眺める(2021年1月)
- P2287R1 Designated-initializers for base classes - [C++]WG21月次提案文書を眺める(2021年2月)
- P2287R2 Designated-initializers for base classes - [C++]WG21月次提案文書を眺める(2023年4月)
- P2287R3 Designated-initializers for base classes - [C++]WG21月次提案文書を眺める(2024年9月)
このリビジョンでの変更は
- P2287R3以降、設計上の制約として非指示付き初期化子を用いて最初の基底クラスのみを初期化可能である一方、2番目の基底クラスメンバは間接的に初期化可能になっていることを明確化する
- この変更に伴い、記述を簡素化
などです。
このリビジョンでの変更は分かりづらいですがどうやら、基底クラスが複数ある場合に初期化の方法をそろえる必要はない(指示付き初期化と基底クラス名による初期化が混在してもよい)ものの、非指示付き初期化は先頭に来なければならず、また初期化式が重複することは許可しない、ということを言っているようです。なお、これは厳密にはこのリビジョンでの変更ではありません。
struct F { int f; }; struct G { int g; }; struct H : F, G { int h; }; auto h1 = H{{.f=1}, {.g=2}, .h=3}; // ok auto h2 = H{{.f=1}, .g=2, .h=3}; // ok, 基底クラスの初期化方法は混在可能 auto h3 = H{F{1} , .g=2, .h=3}; // ok, 同上 auto h4 = H{{.f=1}, G{2}, .h=3}; // ok, 非指示付き初期化(`{.f=1}, G{2}`)は初期化子列の先頭にある auto h5 = H{.f=1, G{2}, .h=3}; // ill-formed, 非指示付き初期化(`G{2}`)が指示付き初期化(`.f=1`)よりも後ろに現れている auto h6 = H{{.f=1}, {.g=2}, .g=3, .h=4}; // ill-formed: Gのメンバを異なる方法で初期化しようとしている
P2414R6 Pointer lifetime-end zap proposed solutions
Pointer lifetime-end zapと呼ばれる問題の解決策の提案。
以前の記事を参照
- P2414R0 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2021年07月)
- P2414R1 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2021年08月)
- P2414R2 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2023年12月)
- P2414R3 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2024年04月)
- P2414R4 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2024年08月)
- P2414R5 Pointer lifetime-end zap proposed solutions - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- ページ番号を追加
usable_ptr<T>に比較演算子を追加usable_ptr<T>にnullptr_tコンストラクタを追加usable_ptr<T>に基づいてmake_ptr_prospective()を定義するusable_ptr<T>コンストラクタからconstexprを削除し、理由を追加usable_ptr<T>のstd::hash特殊化を追加
などです。
P2663R7 Proposal to support interleaved complex values in std::simd
std::simdでstd::complexをサポートできるようにする提案。
以前の記事を参照
- P2663R0 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2022年10月) - P2663R1 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2023年02月) - P2663R3 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2023年05月) - P2663R4 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2023年10月) - P2663R5 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2023年12月) - P2663R6 Proposal to support interleaved complex values in
std::simd- WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- LEWG/LWGレビューからのフィードバックを適用
- 文言の改善
- コンストラクタと
real/imagアクセサにconstexprを追加
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2719R4 Type-aware allocation and deallocation functions
型を指定する形のnew/delete演算子カスタマイズ方法の提案。
- P2719R0 Type-aware allocation and deallocation functions - WG21月次提案文書を眺める(2024年05月)
- P2719R1 Type-aware allocation and deallocation functions - WG21月次提案文書を眺める(2024年10月)
- P2719R3 Type-aware allocation and deallocation functions - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- 必須の暗黙引数に関する設計選択肢を追加
- 「7.4 Design choice: All implicit parameters are mandatory」
などです。
P2758R5 Emitting messages at compile time
コンパイル時に任意の診断メッセージを出力できるようにする提案。
以前の記事を参照
- P2758R0 Emitting messages at compile time - WG21月次提案文書を眺める(2023年01月)
- P2758R1 Emitting messages at compile time - WG21月次提案文書を眺める(2023年12月)
- P2758R2 Emitting messages at compile time - WG21月次提案文書を眺める(2024年02月)
- P2758R3 Emitting messages at compile time - WG21月次提案文書を眺める(2024年05月)
- P2758R4 Emitting messages at compile time - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
などです。
P2781R6 std::constexpr_wrapper
↓
P2781R7 std::constexpr_wrapper
↓
P2781R8 std::constexpr_wrapper
コンパイル時定数オブジェクトを生成するクラスの提案。
以前の記事を参照
- P2781R2
std::constexpr_v- WG21月次提案文書を眺める(2023年05月) - P2781R3
std::constexpr_v- WG21月次提案文書を眺める(2023年07月) - P2781R4
std::constexpr_v- WG21月次提案文書を眺める(2024年02月) - P2781R5
std::constexpr_wrapper- WG21月次提案文書を眺める(2024年12月)
R6での変更は、LEWGレビューを受けての文言修正です。
R7での変更は、LWGレビューを受けての文言変更で以下のものです
constant_wrapperの2つ目のテンプレートパラメータからexposition-onlyを削除operator,を削除cw-fixed-valueのセマンティクスを言葉で表現するように変更operator&&とoperator||に!is_constructible_v<>制約を追加operator()の制約をinvocable<value_type>からinvocable<const value_type&>に変更std::spanで使用されているintegral-constant-like(説明専用)の定義をconstant_wrapperと互換性を持つように変更
このリビジョンでの変更は
operator,をdeleteで再導入valueを返すoperator()を削除(constant_wrapperを返すものは残る)cw-fixed-valueの恒等推論補助を削除
などです。
この提案は2025年6月の全体会議で承認され、C++26に採択されています。
P2786R12 Trivial Relocatability For C++26
↓
P2786R13 Trivial Relocatability For C++26
trivially relocatableをサポートするための提案。
以前の記事を参照
- P2786R0 Trivial relocatability options - WG21月次提案文書を眺める(2023年02月)
- P2786R1 Trivial relocatability options - WG21月次提案文書を眺める(2023年05月)
- P2786R2 Trivial relocatability options - WG21月次提案文書を眺める(2023年07月)
- P2786R3 Trivial relocatability options - WG21月次提案文書を眺める(2023年10月)
- P2786R4 Trivial relocatability options - WG21月次提案文書を眺める(2024年02月)
- P2786R5 Trivial relocatability options - WG21月次提案文書を眺める(2024年04月)
- P2786R6 Trivial relocatability options - WG21月次提案文書を眺める(2024年05月)
- P2786R7 Trivial Relocatability For C++26 - WG21月次提案文書を眺める(2024年09月)
- P2786R8 Trivial Relocatability For C++26 - WG21月次提案文書を眺める(2024年10月)
- P2786R9 Trivial Relocatability For C++26 - WG21月次提案文書を眺める(2024年12月)
R12での変更は
trivially_relocate_at()を削除memberwise_trivially_relocatable()をtrivially_relocatable_if_eligible()へ変更memberwise_replaceable()をreplaceable_if_eligible()に変更
このリビジョンでの変更は
- 認証済みのポインタに対するFAQ項目の追加
- 書式と文言の全体的な改善
- 多態的なメンバを持つ共用体が
trivially relocatableになるかを実装定義にした - Annex Cの追加(compatibility changes)
is_nothrow_relocatableで破棄可能性をチェックするようにしたtrivially_relocate()とrelocate()の事前条件がpotentially overlapping subobjectsの観点から指定されるようになったtrivially_relocate()の事後条件が、オブジェクト表現から仮想関数テーブルを除外するようになったrelocate()の事前条件を追加relocate()が配列のシーケンスでも機能するようにした
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2825R5 Overload resolution hook: declcall( unevaluated-call-expression )
与えられた式が呼び出す関数の関数ポインタを取得する言語機能の提案。
以前の記事を参照
- P2825R0 calltarget(unevaluated-call-expression) - WG21月次提案文書を眺める(2023年02月)
- P2825R2 Overload Resolution hook: declcall(unevaluated-postfix-expression) - WG21月次提案文書を眺める(2024年04月)
- P2825R3 Overload Resolution hook: declcall(unevaluated-postfix-expression) - WG21月次提案文書を眺める(2024年12月)
- P2825R4 Overload resolution hook: declcall( unevaluated-call-expression ) - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- motivationセクションの拡張
- devirtualized pointersに関する設計上の疑問を解決
- CWGによる文言レビューに基づく修正
- devirtualized pointerの値と
final関数の比較に関する疑問を追加 - 実装経験セクションを追加
などです。
devirtualized pointersとは仮想メンバ関数をdeclcall()した時に得られるポインタのことで、正しくはdevirtualized member function pointerと呼ばれています。
struct B { virtual B* f() { return this; } }; struct D : B { D* f() override { return this; } }; void g() { D d; B& rb = d; // d, but type is ref-to-B /// 通常の呼び出し例 d.f(); // calls D::f rb.f(); // calls D::f d.B::f(); // calls B::f auto pf = &B::f; (d.*pf)(); // calls D::f (!) /// declcall()の場合 auto b_f = declcall(d.B::f()); // 型は`B* (B::*) ()` auto rb_f = declcall(rb.f()); // 型は`B* (B::*) ()` auto d_f = declcall(d.f()); // 型は`D* (D::*) ()` (d.*rb_f)(); // 確実に`D::f`を呼ぶ, rb.f() と同じ呼び出し結果 (d.*d_f)(); // 確実に`D::f`を呼ぶ, d.f() と同じ呼び出し結果 (d.*b_f)(); // `B::f`と`D::f`のどちらを呼ぶ? }
この提案では、一番最後の(d.*b_f)()はB::f()を呼び出すようにすることを提案しています。ところで、このb_fのような関数ポインタ(派生クラスのメンバ関数ポインタとしての基底クラス仮想関数へのポインタ)を取得する方法は今まで無かったようで、この提案ではこの関数ポインタのことをdevirtualized pointerと呼んでいます(ただし、GCC拡張には存在していた様子)。
上記例にあるように、devirtualized pointerの型は通常のメンバ関数ポインタの型と区別がつかないようにされています(提案ではこれにより、メンバ関数ポインタの呼び出し構文を用いたジェネリックプログラミングが可能になる、としています...)。
実装経験では、clangフォークでの実装に関する報告と、devirtualized pointersにABIの懸念がないことなどが報告されています。
P2830R10 Standardized Constexpr Type Ordering
std::type_info::before()をconstexprにする提案。
以前の記事を参照
- P2830R0 constexpr type comparison - WG21月次提案文書を眺める(2023年04月)
- P2830R1 constexpr type comparison - WG21月次提案文書を眺める(2023年12月)
- P2830R3 constexpr type comparison - WG21月次提案文書を眺める(2024年04月)
- P2830R4 Standardized Constexpr Type Ordering - WG21月次提案文書を眺める(2024年05月)
- P2830R7 Standardized Constexpr Type Ordering - WG21月次提案文書を眺める(2024年12月)
- P2830R9 Standardized Constexpr Type Ordering - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は、文言の改善のみです。
この提案は2025年6月の全体会議で承認され、C++26に採択されています。
P2841R7 Concept and variable-template template-parameters
コンセプトを受け取るためのテンプレートテンプレートパラメータ構文の提案。
以前の記事を参照
- P2841R0 Concept Template Parameters - WG21月次提案文書を眺める(2023年05月)
- P2841R1 Concept Template Parameters - WG21月次提案文書を眺める(2023年10月)
- P2841R2 Concept Template Parameters - WG21月次提案文書を眺める(2024年04月)
- P2841R3 Concept Template Parameters - WG21月次提案文書を眺める(2024年05月)
- P2841R4 Concept and variable-template template-parameters - WG21月次提案文書を眺める(2024年09月)
- P2841R5 Concept and variable-template template-parameters - WG21月次提案文書を眺める(2024年10月)
- P2841R6 Concept and variable-template template-parameters - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- template-parameterとtemplateparameterという用語の使用法を一貫させ、文言をリベース
- non-type template parameterからconstant template parameterへの名称変更についての編集上の修正
- CWGのレビューを反映
- コンセプトテンプレートパラメータと非コンセプトテンプレートパラメータの両方を含む畳み込み式はill-formedとする
などです。
コンセプトテンプレートパラメータと非コンセプトテンプレートパラメータの両方を含む畳み込み式はill-formedとする
とは次のようなものです
template <typename T, template <typename> concept C> struct wrapper{}; template <typename... T, template <typename> concept... CTs> int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // #3 int err = f(wrapper<int, A>{}, wrapper<int, B>{}); // error: #3の畳み込み式で異なる種類のテンプレートパラメータが混在して使用されている
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2843R2 Preprocessing is never undefined
プリプロセッサに存在する未定義動作を取り除く提案。
以前の記事を参照
- P2843R0 Preprocessing is never undefined - WG21月次提案文書を眺める(2023年05月)
- P2843R1 Preprocessing is never undefined - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- ほとんどの場合のill-formedケースにおいての診断要件を確定
//commentsは空白文字の有無にかかわらず常にwell-formed- 実装用に予約された名前の仕様は依然としてIFNDRのまま
- 大きな整数を含む
#lineはill-formed #演算子(文字列化)内の生文字列リテラルから改行文字をエスケープする- CWGレビューを受けての文言修正
- N5008にリベース
などです。
P2846R6 reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges
遅延評価のため要素数が確定しない range の ranges::to を行う際に、推定の要素数をヒントとして知らせる ranges::reserve_hint CPO を追加する提案。
以前の記事を参照
- P2846R0
size_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2023年05月) - P2846R1
size_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2023年09月) - P2846R2
reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2024年05月) - P2846R3 reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2024年09月)
- P2846R4
reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2024年10月) - P2846R5
reserve_hint: Eagerly reserving memory for not-quite-sized lazy ranges - WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は
- 機能テストマクロの日付修正
- 必要に応じて
to-unsigned-likeを使用 approximately_sized_rangeでは、非forward_rangeに対するbegin()の呼び出しがwell-definedではない場合があることを指定する- コンテナ要件に対する文言を追加
reserve_hintの値が0以上かつrange_difference_tで表現可能であることを指定- ”performs no reallocation”という文言を修正
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2863R9 Review Annex D for C++26
現在非推奨とマークされている機能について、C++26で削除/復帰を検討する提案。
以前の記事を参照
- P2863R0 Review Annex D for C++26 - WG21月次提案文書を眺める(2023年05月)
- P2863R1 Review Annex D for C++26 - WG21月次提案文書を眺める(2023年08月)
- P2863R2 Review Annex D for C++26 - WG21月次提案文書を眺める(2023年10月)
- P2863R3 Review Annex D for C++26 - WG21月次提案文書を眺める(2023年12月)
- P2863R4 Review Annex D for C++26 - WG21月次提案文書を眺める(2024年02月)
- P2863R5 Review Annex D for C++26 - WG21月次提案文書を眺める(2024年04月)
- P2863R7 Review Annex D for C++26 - WG21月次提案文書を眺める(2024年07月)
- P2863R8 Review Annex D for C++26 - WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は主に追跡中の提案のステータス更新です。
P2873R3 Remove Deprecated locale category facets for Unicode from C++26
C++20で非推奨とされたロケールカテゴリファセットをC++26で削除する提案。
以前の記事を参照
- P2873R0 Remove Deprecated locale category facets for Unicode from C++26 - WG21月次提案文書を眺める(2023年05月)
- P2873R1 Remove Deprecated locale category facets for Unicode from C++26 - WG21月次提案文書を眺める(2024年04月)
- P2873R2 Remove Deprecated locale category facets for Unicode from C++26 - WG21月次提案文書を眺める(2024年07月)
このリビジョンでの変更は、文言の変更とレビュー記録の追記などです。
P2876R2 Proposal to extend std::simd with more constructors and accessors
std::simdに対して、利便性向上のために標準ライブラリにあるデータ並列型等のサポートを追加する提案。
以前の記事を参照
- P2876R0 Proposal to extend std::simd with more constructors and accessors - WG21月次提案文書を眺める(2023年05月)
- P2876R1 Proposal to extend std::simd with more constructors and accessors - WG21月次提案文書を眺める(2024年05月)
このリビジョンでの変更は
- 提案から初期化子リストを削除
- 文言の追加
などです。
P2899R1 Contracts for C++ - Rationale
P2900のContracts提案に関する、議論の流れや設計根拠についてまとめた文書。
以前の記事を参照
このリビジョンでの変更は
- P2900R14に合わせて更新
- “Implementation-Defined Behavior”セクションを追加
- 説明の明確化等の修正
- 参考文献の追加
などです。
P2900R14 Contracts for C++
以前の記事を参照
- P2900R1 Contracts for C++ - WG21月次提案文書を眺める(2023年10月)
- P2900R3 Contracts for C++ - WG21月次提案文書を眺める(2023年12月)
- P2900R4 Contracts for C++ - WG21月次提案文書を眺める(2024年01月)
- P2900R5 Contracts for C++ - WG21月次提案文書を眺める(2024年02月)
- P2900R6 Contracts for C++ - WG21月次提案文書を眺める(2024年04月)
- P2900R7 Contracts for C++ - WG21月次提案文書を眺める(2024年05月)
- P2900R8 Contracts for C++ - WG21月次提案文書を眺める(2024年08月)
- P2900R10 Contracts for C++ - WG21月次提案文書を眺める(2024年10月)
- P2900R12 Contracts for C++ - WG21月次提案文書を眺める(2024年12月)
- P2900R13 Contracts for C++ - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- 仮想関数の
pre/postを再びill-formedに - 適合実装戦略に関する情報を追加し、“Mixed Mode”セクションを追加
result nameをresult bindingへ変更- 文章の細かな明確化
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2933R4 Extend header function with overloads for std::simd
<bit>にあるビット演算を行う関数について、std::simd向けのオーバーロードを追加する提案。
以前の記事を参照
- P2933R0
std::simdoverloads for<bit>header - WG21月次提案文書を眺める(2023年08月) - P2933R1
std::simdoverloads for<bit>header - WG21月次提案文書を眺める(2023年12月) - P2933R2
std::simdoverloads for<bit>header - WG21月次提案文書を眺める(2024年10月) - P2933R3 Extend
<bit>header function with overloads forstd::simd- WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- 不要な注釈を削除
- LEWGは、
rotl/rotrのオーバーロードが提供され、第二引数としてintを取る必要があることを確認 - 制約を簡潔化
- P1928R1に合わせて戻り値テストを変更
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P2988R10 std::optional<T&>
↓
P2988R11 std::optional<T&>
std::optionalが参照を保持することができるようにする提案。
以前の記事を参照
- P2988R0
std::optional<T&>- WG21月次提案文書を眺める(2023年10月) - P2988R1
std::optional<T&>- WG21月次提案文書を眺める(2024年01月) - P2988R3
std::optional<T&>- WG21月次提案文書を眺める(2024年02月) - P2988R4
std::optional<T&>- WG21月次提案文書を眺める(2024年04月) - P2988R5
std::optional<T&>- WG21月次提案文書を眺める(2024年05月) - P2988R6
std::optional<T&>- WG21月次提案文書を眺める(2024年08月) - P2988R7
std::optional<T&>- WG21月次提案文書を眺める(2024年09月) - P2988R8
std::optional<T&>- WG21月次提案文書を眺める(2024年10月) - P2988R9
std::optional<T&>- WG21月次提案文書を眺める(2025年01月)
R10での変更は、基本型/派生型の未定義動作を除去するためのキャストの修正です。
このリビジョンでの変更は、LWGレビューに基づく文言の修正です。
P2996R10 Reflection for C++26
値ベースの静的リフレクションの提案。
以前の記事を参照
- P2996R0 Reflection for C++26 - WG21月次提案文書を眺める(2023年10月)
- P2996R1 Reflection for C++26 - WG21月次提案文書を眺める(2023年12月)
- P2996R2 Reflection for C++26 - WG21月次提案文書を眺める(2024年02月)
- P2996R3 Reflection for C++26 - WG21月次提案文書を眺める(2024年05月)
- P2996R4 Reflection for C++26 - WG21月次提案文書を眺める(2024年07月)
- P2996R5 Reflection for C++26 - WG21月次提案文書を眺める(2024年08月)
- P2996R7 Reflection for C++26 - WG21月次提案文書を眺める(2024年10月)
- P2996R8 Reflection for C++26 - WG21月次提案文書を眺める(2024年12月)
- P2996R9 Reflection for C++26 - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- コア言語の文言の変更
- ライブラリの文言変更
などです。
P3008R4 Atomic floating-point min/max
浮動小数点数型のstd::atomicにおけるfetch_max()/fetch_min()の問題を解消する提案。
以前の記事を参照
- P3008R0 Atomic floating-point min/max - WG21月次提案文書を眺める(2023年10月)
- P3008R1 Atomic floating-point min/max - WG21月次提案文書を眺める(2024年02月)
- P3008R2 Atomic floating-point min/max - WG21月次提案文書を眺める(2024年04月)
- P3008R3 Atomic floating-point min/max - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- Remarks節を統合
- P3309の
constexpr更新を組み込み - いくつかの新しい
<cmath>関数を追加するオプション提案を追加
などです。
P3016R6 Resolve inconsistencies in begin/end for valarray and braced initializer lists
std::valarrayと初期化子リストに対してstd::beginとstd::cbeginを呼んだ場合の他のコンテナ等との一貫しない振る舞いを修正する提案。
以前の記事を参照
- P3016R0 Resolve inconsistencies in
begin/endforvalarrayand braced initializer lists - WG21月次提案文書を眺める(2023年10月) - P3016R1 Resolve inconsistencies in begin/end for valarray and braced initializer lists - WG21月次提案文書を眺める(2023年12月)
- P3016R2 Resolve inconsistencies in begin/end for valarray and braced initializer lists - WG21月次提案文書を眺める(2023年12月)
- P3016R3 Resolve inconsistencies in begin/end for valarray and braced initializer lists - WG21月次提案文書を眺める(2024年04月)
- P3016R4 Resolve inconsistencies in begin/end for valarray and braced initializer lists - WG21月次提案文書を眺める(2024年09月)
- P3016R5 Resolve inconsistencies in begin/end for valarray and braced initializer lists - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- P3623R0のLEWG合意に基づいて、その文言を組み込み
などです。
P3019R13 Vocabulary Types for Composite Class Design
↓
P3019R14 Vocabulary Types for Composite Class Design
動的メモリ領域に構築されたオブジェクトを扱うためのクラス型の提案。
以前の記事を参照
- P3019R0 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2023年10月)
- P3019R3 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2023年12月)
- P3019R6 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2024年02月)
- P3019R8 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2024年04月)
- P3019R9 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2024年09月)
- P3019R10 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2024年10月)
- P3019R11 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2024年12月)
- P3019R12 Vocabulary Types for Composite Class Design - WG21月次提案文書を眺める(2025年01月)
R13での変更は
indirectのoperator=(U&&)からTがcopy-constructibleであることの要件を削除indirectのoperator<=>でfalse < trueではなくstd::strong_ordering::lessを使用するように修正indirectのoperator<=>のvaluelessチェックでのrhsをlhsへ変更- 文言に不足していたカンマを追加
このリビジョンでの変更は
indirectのoperator<=>からnoexceptを削除- タグ付きコンストラクタの説明に明確な例を追加
in_place_type_tと初期化子リストを取るpolymorphicのコンストラクタでis_same_v<U, polymorphic> is false制約を削除polymorphicコンストラクタの制約を一貫して順序付けするindirectにおける不要なUUの導入を削除- appendixの"Constraints and incomplete type support"セクションを更新
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3060R2 Add std::views::indices(n)
0から指定した数の整数シーケンスを生成するRangeアダプタ、views::uptoの提案。
以前の記事を参照
- P3060R0 Add
std::ranges::upto(n)- WG21月次提案文書を眺める(2023年12月) - P3060R1 Add
std::ranges::upto(n)- WG21月次提案文書を眺める(2024年02月)
このリビジョンでの変更は、
views::uptoをviews::indicesに名称変更std::integralではなく説明専用のis-integer-likeを使用するis-integer-likeはboolを排除し実装定義の整数型を含む
などです。
P3070R3 Formatting enums
列挙型の値を簡単にstd::formatにアダプトさせるための、format_asの提案。
以前の記事を参照
- P3070R0 Formatting enums - WG21月次提案文書を眺める(2023年12月)
- P3070R1 Formatting enums - WG21月次提案文書を眺める(2024年10月)
- P3070R2 Formatting enums - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- ADLによってマッチした関数が設計意図に合致すると判断された場合にのみ
format_asを使用するように文言を追加 format_asを列挙型に加えてユーザー定義クラス型にも拡張- LEWG投票結果を追加
などです。
P3074R6 trivial unions (was std::uninitialized)
↓
P3074R7 trivial unions (was std::uninitialized)
定数式において、要素の遅延初期化のために共用体を用いるコードを動作するようにする提案。
以前の記事を参照
- P3074R0 constexpr union lifetime - WG21月次提案文書を眺める(2023年12月)
- P3074R2
std::uninitialized<T>- WG21月次提案文書を眺める(2024年02月) - P3074R3 trivial union (was std::uninitialized
) - WG21月次提案文書を眺める(2024年04月) - P3074R4 trivial unions (was
std::uninitialized<T>) - WG21月次提案文書を眺める(2024年09月) - P3074R5 trivial unions (was
std::uninitialized<T>) - WG21月次提案文書を眺める(2024年12月)
R5及びこのリビジョンでの変更は、CWGレビューに基づく文言の更新です。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3081R2 Core safety profiles for C++26
P3038で提案されている安全性プロファイルの、より具体的な意味論についての提案。
以前の記事を参照
- P3081R0 Core safety Profiles: Specification, adoptability, and impact - WG21月次提案文書を眺める(2024年10月)
- P3081R1 Core safety Profiles: Specification, adoptability, and impact - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
[except.spec]に契約アサーションから送出された例外はnoexcept演算子に影響を与えないという文言を追加index_in_rangeにnoexceptを追加- P3589R0で提案された文言修正をいくつか採用
- EWGのフィードバックを反映し、各プロファイルルールのセクションが文言だけでなくその意図と設計を保持するようにした
- セクション9を追加し、P3589R1およびP3471R2で提案された他の拡張を参照
- EWGのフィードバックを反映し、modernizationsを後の提案に分離
- R0から誤って修正されていたローカル変数初期化についてを復帰
zstring_viewの提案はオプションであり、テレコンレビューで検討できなかったため削除- SG21レビューによる明確化の提案を採用
などです。
この提案はfor C++26となっていますが、C++26には採用されずwhite paperとして作業していくようです。
P3096R6 Function Parameter Reflection in Reflection for C++26
↓
P3096R7 Function Parameter Reflection in Reflection for C++26
C++26に向けた静的リフレクションに対して、関数仮引数に対するリフレクションを追加する提案。
以前の記事を参照
- P3096R0 Function Parameter Reflection in Reflection for C++26 - WG21月次提案文書を眺める(2024年02月)
- P3096R1 Function Parameter Reflection in Reflection for C++26 - WG21月次提案文書を眺める(2024年05月)
- P3096R2 Function Parameter Reflection in Reflection for C++26 - WG21月次提案文書を眺める(2024年09月)
- P3096R3 Function Parameter Reflection in Reflection for C++26 - WG21月次提案文書を眺める(2024年12月)
R6での変更は
- LEWGテレコンの投票結果を追記
- LEWGのフィードバックに基づいて文言を更新
- dependency injectionのサンプルコードを追加
- 宣言内の後置戻り値型を削除
このリビジョンでの変更は
- EWGの投票結果の追加
- LEWGのフィードバックに基づいて文言を更新
などです。
P3104R3 Bit permutations
<bit>にビット置換系操作を追加する提案
以前の記事を参照
- P3104R0 Bit permutations - WG21月次提案文書を眺める(2024年02月)
- P3104R2 Bit permutations - WG21月次提案文書を眺める(2024年05月)
このリビジョンでの変更は
- 文言の修正
bit_compressとbit_expandからl付きのバージョンを削除
などです。
P3111R4 Atomic Reduction Operations
↓
P3111R5 Atomic Reduction Operations
std::atomicにアトミックリダクション操作を追加する提案。
以前の記事を参照
- P3111R0 Atomic Reduction Operations - WG21月次提案文書を眺める(2024年09月)
- P3111R2 Atomic Reduction Operations - WG21月次提案文書を眺める(2024年12月)
- P3111R3 Atomic Reduction Operations - WG21月次提案文書を眺める(2025年01月)
R4での変更はEWGでの投票結果の追記のみです。
このリビジョンでの変更は
- P3309から
constexpr更新を組み込み- 新しい
store_key()はfetch_key()と同じ条件でconstexprになる
- 新しい
- P3008から浮動小数点数の
min/maxを条件付きで組み込み - 機能テストマクロの追加
compare_storeを別の提案に分離(P3544R0)- 名前を
reduce_*からstore_*に、atomic_reduce_*からatomic_store_*に変更
などです。
P3137R3 views::to_input
入力の範囲をinput_rangeに弱めるRangeアダプタ、views::inputの提案。
以前の記事を参照
- P3137R0
views::to_input- WG21月次提案文書を眺める(2024年02月) - P3137R1
views::to_input- WG21月次提案文書を眺める(2024年05月) - P3137R2
views::to_input- WG21月次提案文書を眺める(2024年07月)
このリビジョンでの変更は、文言の修正のみです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3149R9 async_scope -- Creating scopes for non-sequential concurrency
P2300のExecutorライブラリについて、並列数が実行時に決まる場合の並行処理のハンドリングを安全に行うための機能を提供する提案。
以前の記事を参照
- P3149R0 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年02月)
- P3149R2 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年04月)
- P3149R3 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年05月)
- P3149R5 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年07月)
- P3149R6 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年10月)
- P3149R8 async_scope -- Creating scopes for non-sequential concurrency - WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は
- LWGのフィードバックを適用
simple_counting_scope::join/counting_scope::joinで使用される言葉を変更し、LEWGのアンケートで得られた完了動作を明示的に指定する- ✅
joinの完了動作を次のいずれかによって明確に規定する- 条件が満たされた場合、
startメソッド内で同期的に完了させる - 条件が満たされた場合、明示的にスケジューラを作成して非同期的に完了させる
- 条件が満たされた場合、
- ❌ 操作が即時完了する場合はインライン完了ではなくscheduleを設定する
- ❌ 操作が非同期完了する場合はscheduleを設定するのではなくインライン完了する
- ✅
などです。
P3161R3 Unified integer overflow arithmetic
オーバーフローを処理可能な整数演算の提案。
以前の記事を参照
- P3161R1 Unified integer overflow arithmetic - WG21月次提案文書を眺める(2024年04月)
- P3161R2 Unified integer overflow arithmetic - WG21月次提案文書を眺める(2024年07月)
このリビジョンでの変更は
- テンプレートパラメータ数の間違いを修正
- "suggested optimizations and reference implementation"のセクションを追加
などです。
P3179R6 C++ parallel range algorithms
↓
P3179R7 C++ parallel range algorithms
RangeアルゴリズムをExecutionPolicyに対応させる提案。
以前の記事を参照
- P3179R0 C+ parallel range algorithms - WG21月次提案文書を眺める(2024年04月)
- P3179R1 C+ parallel range algorithms - WG21月次提案文書を眺める(2024年05月)
- P3179R2 C++ parallel range algorithms - WG21月次提案文書を眺める(2024年07月)
- P3179R2 C++ parallel range algorithms - WG21月次提案文書を眺める(2024年10月)
- P3179R4 C++ parallel range algorithms - WG21月次提案文書を眺める(2024年12月)
- P3179R5 C++ parallel range algorithms - WG21月次提案文書を眺める(2025年01月)
R6での変更は
rotate_copyをスコープに再追加reverse_copyとmergeの文言を修正- アルゴリズムの戻り値に対する制限付き出力の影響について言及
rotate_copy, reverse_copy, partition_copyの設計上の選択肢を説明- 残りのアルゴリズム(
rotate_copy, reverse_copy, partition_copy)について不足していた文言を追加 - 並列コンテキストでのビューの使用に関する分析を更新
このリビジョンでの変更は
- 境界付き出力を持つアルゴリズムの停止位置に関するLEWGの決定を反映する形で、設計の説明と文言を更新
- 新しいオーバーロードを
freestanding-deletedとしてマーク random-access-sized-rangeコンセプトをsized-random-access-rangeにリネームcopy_if, remove_copy[_if], unique_copy, mergeの文言を改善- LWGへの質問は、関連する文言の横にdrafting notesとして記載する
などです。
P3229R1 Making erroneous behaviour compatible with Contracts
Erroneous Behavior(EB)をContractsのフレームワークに取り込む提案。
以前の記事を参照
このリビジョンでの変更は
- erroneous behaviourという用語の削除を提案しなくなった
- コード例の修正
- 編集上の変更
などです。
この提案はSG21ではコンセンサスを得たもののEWGでは得ることができず、追及は停止されています。
P3230R2 views::unchecked_(take|drop)
より効率的なviews::take/dropである、views::take_exactlyとviews::drop_exactlyの提案。
以前の記事を参照
- P3230R0
views::(take|drop)_exactly- WG21月次提案文書を眺める(2024年04月) - P3230R1
views::(take|drop)_exactly- WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- 文言に事前条件を追加
- 最新のドラフトにリベース
などです。
P3242R1 Copy and fill for mdspan
C++23 で導入された std::mdspan に対して、copy 操作および fill 操作を行う関数を <mdspan> に追加する提案。
以前の記事を参照
このリビジョンでの変更は、異なるサイズのmdspan間でのコピーに関する議論を追加したことです。
P3248R3 Require [u]intptr_t
(u)intptr_tを必須にする提案。
以前の記事を参照
- P3248R0 Require [u]intptr_t - WG21月次提案文書を眺める(2024年05月)
- P3248R1 Require [u]intptr_t - WG21月次提案文書を眺める(2024年07月)
- P3248R2 Require [u]intptr_t - WG21月次提案文書を眺める(2024年09月)
このリビジョンでの変更は
- SG22/WG14にてCとの互換性に関する懸念がないことを確認
- P3348の採用を考慮して文言を調整
などです。
P3284R3 write_env and unstoppable Sender Adaptors
receiverの環境に値を書き込むためのwrite_envと、それを用いたunstoppableアルゴリズムの提案。
以前の記事を参照
- P3284R0
finally,write_env, andunstoppableSender Adaptors - WG21月次提案文書を眺める(2024年05月) - P3284R1
finally,write_env, andunstoppableSender Adaptors - WG21月次提案文書を眺める(2024年08月) - P3284R2
finally,write_env, andunstoppableSender Adaptors - WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は明確ではないですが、文言の調整のみのようです。
P3287R3 Exploration of namespaces for std::simd
std::simdに関するAPIを標準ライブラリ中にどのように配置するのかについてを探る提案。
以前の記事を参照
- P3287R0 Exploration of namespaces for
std::simd- WG21月次提案文書を眺める 2024年05月 - P3287R1 Exploration of namespaces for
std::simd- WG21月次提案文書を眺める 2024年10月 - P3287R2 Exploration of namespaces for
std::simd- WG21月次提案文書を眺める 2024年12月
このリビジョンでの変更は
- 異なる名前空間を使用
simd_maskの名前変更を行わない- 文言の簡素化
などです。
ここでは、R1で代替案8として提案されていたものが採用されています。ただし、std::simd名前空間ではなくstd::datapar名前空間を使用するようになっています。
これにより、std::simdはstd::datapar::simdになり、simd_mask以外の関連する名前からsimd_プリフィックスが削除されます。そして、数学関数をはじめとするstd::datapar::simdのオーバーロードを持つ関数はstd直下にusingされます。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3296R4 let_async_scope
提案中のcounting_scopeの問題を修正する提案。
以前の記事を参照
- P3296R0
let_with_async_scope- WG21月次提案文書を眺める(2024年05月) - P3296R1
let_async_scope- WG21月次提案文書を眺める(2024年07月) - P3296R2
let_async_scope- WG21月次提案文書を眺める(2024年10月) - P3296R3
let_async_scope- WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は
- 非同期スコープ型の仕様を修正
- 明示的に環境を取るか取らないかで
spawnを2つのオーバーロードに分けた - 状態から明示的な
mutexを削除
などです。
P3319R3 Add an iota object for simd (and more)
↓
P3319R4 Add an iota object for simd (and more)
↓
P3319R5 Add an iota object for simd (and more)
std::simdオブジェクト(SIMDレジスタ)を連番の値で初期化するAPIの提案。
以前の記事を参照
- P3319R0 Add an iota object for simd (and more) - WG21月次提案文書を眺める(2024年05月)
- P3319R1 Add an iota object for simd (and more) - WG21月次提案文書を眺める(2024年07月)
- P3319R2 Add an iota object for simd (and more) - WG21月次提案文書を眺める(2024年12月)
R3での変更は
- 議論中の命名規則を整理
- オーバーフローについてのセクションを追加
- 「Mandate “no overflow”」を文言に追加
R4での変更は
このリビジョンでの変更は
iotaにvectorizableを要求するようにした
などです。
P3331R1 Accessing The First and Last Elements in Associative Containers
連想コンテナに対して、2つの関数front()、back()を追加する提案。
以前の記事を参照
このリビジョンでの変更は
- 動機づけの改善
- typo修正
などです。
P3349R1 Converting contiguous iterators to pointers
contiguous_iteratorをポインタとして扱うことができるようにするために、標準ライブラリにおける要件を強化する提案。
以前の記事を参照
このリビジョンでの変更は、イテレータが境界チェック機能を持っている場合、それが失われないことを明確化したことです。
イテレータ範囲をポインタに置き換える際に、to_address(i)の先頭ポインタから終端を求めるのではなくto_address(i + n)で終端ポインタを得るように指定することで、イテレータの持つ境界チェック能力(がある場合)を維持できるようにしています。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。なお、C++20へのDRとされたようです。
P3365R1 Remove the Deprecated iterator Class Template from C++26
非推奨だったstd::iteratorクラステンプレートを削除する提案。
以前の記事を参照
このリビジョンでの変更は
- LEWGのテレコンレビューを記録
- N5001にリベース
- 表とリストへの項目追加に関する文言を整理
- Annex Cの文言の追加
などです。
P3366R1 Remove Deprecated Atomic Initialization API from C++26
非推奨だったstd::atomicの初期化関数を削除する提案。
以前の記事を参照
このリビジョンでの変更は
- SG1/LEWGのテレコンレビューを記録
- N5008にリベース
- 表とリストへの項目追加に関する文言を整理
- Annex Cの文言の追加
- Annex Dの文言の追加
などです。
P3367R4 constexpr coroutines
コンパイル時でもコルーチンを動作可能にする提案。
以前の記事を参照
- P3367R0 constexpr coroutines - WG21月次提案文書を眺める(2024年10月)
- P3367R2 constexpr coroutines - WG21月次提案文書を眺める(2024年12月)
- P3367R3 constexpr coroutines - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は、コルーチン評価内でのみco_await, co_yieldの(定数式での)仕様を許可するようにしたことです。
P3372R3 constexpr containers and adapters
標準のコンテナを全てconstexprにする提案。
以前の記事を参照
- P3372R0 constexpr containers and adapters - WG21月次提案文書を眺める(2024年08月)
- P3372R1 constexpr containers and adapters - WG21月次提案文書を眺める(2024年09月)
- P3372R2 constexpr containers and adapters - WG21月次提案文書を眺める(2024年10月)
このリビジョンでの変更は機能テストマクロの更新です。
この提案は2024年11月の全体会議で承認され、C++26に向けて採択されています。
P3378R2 constexpr exception types
例外型をconstexpr指定する提案。
以前の記事を参照
- P3378R0
constexprexception types - WG21月次提案文書を眺める(2024年10月) - P3378R1
constexprexception types - WG21月次提案文書を眺める(2024年12月)
このリビジョンでの変更は、__cpp_lib_constexpr_exceptionsの値を更新するようにしたことです。
P3383R2 mdspan.at()
std::mdspanに.at()メンバ関数を追加する提案。
以前の記事を参照
このリビジョンでの変更は
- 機能テストマクロのバンプを削除
operator[]などと同じパターンに従うように文言を調整- 最新のドラフトにリベース
などです。
P3385R4 Attributes reflection
リフレクションにおいて、エンティティに指定されている属性の情報を取得・付加できるようにする提案。
以前の記事を参照
- P3385R0 Attributes reflection - WG21月次提案文書を眺める(2024年09月)
- P3385R1 Attributes reflection - WG21月次提案文書を眺める(2024年10月)
- P3385R2 Attributes reflection - WG21月次提案文書を眺める(2024年12月)
- P3385R3 Attributes reflection - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- typo修正
- splice-expressionの参照に関する文言を修正
- 著者を更新
- P2996R9ヘリベース
などです。
P3394R2 Annotations for Reflection
C++任意のエンティティ(宣言)に対して静的リフレクションのためのアノテーションを付加できるようにする提案。
以前の記事を参照
- P3394R0 Annotations for Reflection - WG21月次提案文書を眺める(2024年12月)
- P3394R1 Annotations for Reflection - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- 注入された宣言に関するP2996のスコープ制限を緩和
- エンティティの定義で、それ自身の注入宣言を生成できるようにする
- ライブラリAPIを次のものみに削減
is_annotationannotations_ofannotations_of_with_type(vector<info>を返す2引数関数)annotate
などです。
P3395R1 Fix encoding issues and add a formatter for std::error_code
↓
P3395R2 Fix encoding issues and add a formatter for std::error_code
std::error_codeをフォーマット可能にする提案。
以前の記事を参照
R1での変更は
- この変更がLWG4156も修正していることを受けて、提案タイトルを変更
error_category::name()が通常のリテラルエンコーディングを返すことを規定- 標準規格内でのほかの部分との整合性を保つために、リテラルエンコーディングがUTF-8でない場合
error_category::message()での文字コード変換を実装定義にする
このリビジョンでの変更は
- マップ内のエラーコードをフォーマットする際の曖昧さを回避するためにデバッグ形式を追加
などです。
P3400R1 Specifying Contract Assertion Properties with Labels
契約アサーションに対してラベルを指定する機能の提案。
以前の記事を参照
このリビジョンでの変更は
などです。
P3417R1 Handling exceptions thrown from contract predicates
契約条件式の評価中に送出された例外と、そうでない例外を区別して違反ハンドラで処理するようにする提案。
以前の記事を参照
このリビジョンでの変更は
- R0に寄せられたフィードバックを適用
- 編集上の修正
などです。
この提案は情報提供のみを目的とするようになり、提案をしなくなったようです。
P3430R3 simd issues: explicit, unsequenced, identity-element position, and members of disabled simd
std::simd(P1928)のLWGレビューで見つかったIssueとその解決についてまとめた提案。
以前の記事を参照
- P3430R0 simd issues: explicit, unsequenced, identity-element position, and members of disabled simd - WG21月次提案文書を眺める(2024年10月)
- P3430R1 simd issues: explicit, unsequenced, identity-element position, and members of disabled simd - WG21月次提案文書を眺める(2024年12月)
- P3430R2 simd issues: explicit, unsequenced, identity-element position, and members of disabled simd - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は良くわかりません。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3441R1 Rename simd_split to simd_chunk
↓
P3441R2 Rename simd_split to simd_chunk
std::simdのsimd_splitという機能の名前をsimd_chunkに変更する提案。
以前の記事を参照
R1での変更は
simd_chunk_nをsimd_chunkに変更- 各オーバーロードをそれぞれ独立した節で区切るために文言を変更
このリビジョンでの変更は
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3442R1 [[invalidate_dereferencing]] attribute
関数に渡されるポインタが無効化されることをコンパイラに通知するための属性、[[invalidate_dereferencing]]の提案。
以前の記事を参照
このリビジョンでの変更は
- 「Integration with similar work」セクションを追加
- SG23はP3442とP3465の調和について検討するよう要請
- P1179はLifetime Safety TSとして追及されるべき
などです。
P3471R3 Standard Library Hardening
↓
P3471R4 Standard Library Hardening
標準ライブラリに堅牢化モードを導入する提案。
以前の記事を参照
- P3471R0 Standard library hardening - WG21月次提案文書を眺める(2024年10月)
- P3471R2 Standard Library Hardening - WG21月次提案文書を眺める(2024年12月)
R3での変更は
void型に対するexpected特殊化を対象に加える
このリビジョンでの変更は
- 契約違反がどのように発生するかを明確化
- 事前条件を記述する際のライブラリ文言の一貫性を改善
などです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3472R1 Make fiber_context::can_resume() const
fiber_context::can_resume()をconstメンバ関数にする提案。
以前の記事を参照
このリビジョンでの変更は、文言を追加したことです。
P3475R2 Defang and deprecate memory_order::consume
memory_order_consumeを非推奨化する提案。
以前の記事を参照
- P3475R0 Defang and deprecate
memory_order::consume- WG21月次提案文書を眺める(2024年10月) - P3475R1 Defang and deprecate
memory_order::consume- WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は、文言の修正のみです。
この提案は2025年2月の全体会議で承認され、C++26に採択されています。
P3477R3 There are exactly 8 bits in a byte
↓
P3477R4 There are exactly 8 bits in a byte
↓
P3477R5 There are exactly 8 bits in a byte
1バイトを8ビットであると規定するようにする提案。
以前の記事を参照
- P3477R0 There are exactly 8 bits in a byte - WG21月次提案文書を眺める(2024年10月)
- P3477R1 There are exactly 8 bits in a byte - WG21月次提案文書を眺める(2024年12月)
- P3477R2 There are exactly 8 bits in a byte - WG21月次提案文書を眺める(2025年01月)
R3での変更は
int16_t, int32_t, int64_tと符号なしの型についての議論を拡張し、[cstdint.syn]への変更を明確にするための文言の更新と[basic.fundamental]への変更- 複雑さに関する動機付けを詳しく説明
- 文言の更新
- 「§ 5 Other languages」にほかの言語とそれらのバイト選択に関するセクションを追加
R4での変更は
- ライブラリの変更を削除し、言語の変更のみを進める
このリビジョンでの変更は特にないようですが、EWGにおいてリジェクトされたことを追記しています。
P3480R4 std::simd is a range
std::simdをrangeにする提案。
以前の記事を参照
- P3480R0 std::simd is a range - WG21月次提案文書を眺める(2024年10月)
- P3480R1 std::simd is a range - WG21月次提案文書を眺める(2024年12月)
- P3480R3 std::simd is a range - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は、simdのサブ名前空間の導入を受けての文言の更新のみです。
P3481R2 std::execution::bulk() issues
std::execution::bulk()の改善提案。
以前の記事を参照
- P3481R0 Summarizing
std::execution::bulk()issues - WG21月次提案文書を眺める(2024年12月) - P3481R1 Summarizing
std::execution::bulk()issues - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- SG1レビューのフィードバックを反映
- P3564R0の変更を組み込み
- 並行処理を実行するスケジューラにおいてカスタムされていない
bulk_unchunked()の呼び出しをill-formedにする
- 並行処理を実行するスケジューラにおいてカスタムされていない
bulk_unchunked()の実行ポリシー引数を削除- "lack of resources"の場合にエラーとする
などです。
P3482R1 Design for C++ networking based on IETF TAPS
IETFのTAPSに基づいたネットワークライブラリのAPIの提案。
以前の記事を参照
このリビジョンでの変更は
などです。
P3491R2 define_static_{string,object,array}
コンパイル時に構築した文字列や配列などを静的ストレージに昇格させて実行時に持ち越せるようにするライブラリ機能の提案。
以前の記事を参照
- P3491R0
define_static_{string,object,array}- WG21月次提案文書を眺める(2024年12月) - P3491R1
define_static_{string,object,array}- WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は
- すべての文字列リテラル型のサポートを追加
- CWG2765の採用を前提として文言を調整
などです。
P3492R1 Sized deallocation for placement new
↓
P3492R2 Sized deallocation for placement new
配置new式において、オブジェクト初期化失敗時に選択されるdelete演算子の候補として、サイズ引数を取るものを考慮するようにする提案。
以前の記事を参照
このリビジョンでの変更は明確ではないですが
- セクションの追加
- "2. Implementation divergence"
- "5. Implementation experience"
- "6. Effect on the standard"
- "7. Proposed wording"
std::size_val_t引数が推定された場合、そのdeleteはここで提案しているサイズ付き解放関数とはみなされない- 既存の配置
new関数テンプレートとのマッチングを回避するため
- 既存の配置
- 新しい配置
delete関数の探索(マッチング)時に複数の候補が見つかった場合ill-formedとすることを明確化- これは
newの場合と異なる(エラーにならずどちらも無視する)
- これは
- 新しい配置
delete関数のサイズパラメータの位置は、void*の直後かつstd::align_val_t(存在する場合)の前、と明確化 - 機能テストマクロの追加
- CWG1628の修正の適用
- 配置
deleteの適合性の明確化- 配置
delete関数のマッチングには対応するnew関数の可変長性(可変長引数を取るかどうか)が考慮される- 可変長引数を持つ
newの呼び出しに対して、可変長引数を持たないdeleteはマッチしない(逆も)
- 可変長引数を持つ
delete関数宣言の末尾引数にデフォルト引数を追加するとマッチングが妨げられる
- 配置
- 提案する文言の追加
などです。
配置deleteの適合性の明確化、に関するサンプルコード
// 1. 配置`delete`関数のマッチングには対応する`new`関数の可変長性(可変長引数を取るかどうか)が考慮される void* operator new(size_t s, alloc_1& al, ...); void operator delete(void* p, alloc_1& al); // Never used void* operator new(size_t s, alloc_2& al); void operator delete(void* p, alloc_2& al, ...); // Never used
// 2. `delete`関数宣言の末尾引数にデフォルト引数を追加するとマッチングが妨げられる void* operator new(size_t s, alloc& al); void operator delete(void* p, alloc& al, int = 0); // Never used
P3499R1 Exploring strict contract predicates
非緩和契約の設計についての提案。
以前の記事を参照
このリビジョンでの変更は
- 投票結果の引用の誤りを修正
- 編集上の修正
などです。
P3500R1 Are Contracts "safe"?
C++ Contracts提案の安全性に対する懸念点からの反対意見に対しての解消のための説明文書。
以前の記事を参照
このリビジョンでの変更は
- Section 3.1のコード例の誤りを修正
- Section 2.1の安全性の異なる定義についての議論を拡張
- 提案全体の編集上の修正
などです。
P3503R1 Make type-erased allocator use in promise and packaged_task consistent
↓
P3503R2 Make type-erased allocator use in promise and packaged_task consistent
std::promiseとstd::packaged_taskのアロケータ対応における問題を修正する提案。
以前の記事を参照
R1およびこのリビジョンでの変更は、文言の修正のみです。
P3505R0 Fix the default floating-point representation in std::format
std::format()における浮動小数点数出力時のデフォルトの表現(gオプション)を修正する提案。
std::format()の浮動小数点数出力時のフォーマット方法はstd::to_charsを用いて指定されており、これはCロケールと同じ出力を規定するために実質的にCの標準によって指定されています。
Cロケールによるデフォルトの出力では、出力後の浮動小数点数表現が短くなるように指数表記と固定小数表記を切り替えますが、この「短くなる」の意味が出力文字数によるものであると誤解されて実装されてしまう場合があることによって、std::format()のデフォルトの浮動小数点数出力も間違った表現を選択する場合があるようです。
たとえば、100000.0と120000.0は本来同じ形式で出力される必要があります(たとえばpythonの例)
>>> 100000.0 100000.0 >>> 120000.0 120000.0
しかし、std::format()の場合異なった形式によって出力されます
auto s1 = std::format("{}", 100000.0); // s1 == "1e+05" auto s2 = std::format("{}", 120000.0); // s2 == "120000"
これによって、本来の意味の可能な限り短い表記が順守されず、表現可能な精度の外の値(garbage digits)が出力されてしまいます
auto s = std::format("{}", 1234567890123456700000.0); // s == "1234567890123456774144"
最後の5桁74144は意味のない値であり、現代の一般的な浮動小数点数フォーマットでは出力されることがないはずの値です。例えば、pythonはこの場合に指数表記を選択することでこれを回避します
>>> 12345678901234567800000.0 1.2345678901234568e+22
正しい浮動小数点数出力を行うことのできる既存の実装ではこのような意味のない桁を出力できないため、std::format()の実装に当たってはこのような下位桁を計算するための特別な実装を必要としており、それによってフォーマットパフォーマンスの低下を招いています。
正しい浮動小数点数表現とは Steele & White (1990) で定義されたものをベースとしているようで、そこではそのような出力アルゴリズムの特性として次の4点を指摘しています
- 情報の損失が発生しない
- 出力値の丸めによって、元の値を正確に復元できる
- 無意味な桁("garbage digits")が生成されない
- 出力値は適切に丸められる
- 丸め処理の際に桁を繰り返す必要がない
重要なのはこの2番目の項目で、これは簡潔性("shortness")の保証と呼ばれているようです。簡潔性保証はアルゴリズムが他の要件(特にラウンドトリップ保証)を満たすために必要な最小の桁数で出力するべき、という意味であり、これは仮数の小数点以下の桁数にのみ着目したもので、指数や小数点などは考慮されないものののようです。
前述のように、C++においてはこの簡潔性についての言及を出力文字数の短さと解釈してしまっていることで、現在のstd::format()の浮動小数点数出力に問題が起きています。
この提案では、本来の意味での簡潔性を指定するように規定を修正することで、std::format()の浮動小数点数出力を正しいものに修正しようとしています。
具体的には、フォーマット対象の浮動小数点数値が$[10^{-4}, 10n)$の範囲にある場合は固定小数形式を使用し、そうでなければ指数形式を使用する、ように明示的に指定しています。なお、ここでの$10n$は、浮動小数点数型をFP、m = std::numeric_limits<FP>::digits + 1として、$2m$を最も近い10の累乗値に丸め下げたものです。
例えばdouble型の場合std::numeric_limits<FP>::digitsは53となり、$254$となり、これを最も近い10の累乗値に丸め下げたものは$1016$となります。これらの値はpythonやrust、swiftやjava等と同じ値になっているようです。
この下限値は絶対値が小さい値の出力について固定少数形式を回避し、上限値は大きい値の出力について固定少数形式を回避しようとするものです。
これによって、ほかの主要なプログラミング言語における出力と同等の出力得るようになるとともに、無意味な桁を出力するためのパフォーマンス低下を回避することができます。また、これは{fmt}ライブラリにおいて少なくとも6年前から実装され出荷されているとのことです。
この変更は破壊的変更となるものの、ABIやラウンドトリップの保証には影響がなく、浮動小数点数の正確な表現への依存は通常推奨されないため、影響は中程度であるとしています。
P3516R1 Uninitialized algorithms for relocation
未初期化メモリに対するリロケーションアルゴリズムのライブラリ機能の提案。
以前の記事を参照
このリビジョンでの変更は
- P2786R11ヘリベース
- 文言の修正
などです。
P3526R0 Container truncation
指定した個数の要素だけを残す(溢れた要素を切り捨てる)truncate()をコンテナに追加する提案。
std::vectorをはじめとするコンテナには.resize()があり、これによってコンテナ長の縮小と拡大の両方を行うことができます。しかし、拡大の場合にnoexceptを仮定できないため、.resize()はnoexceptではありません(動的メモリ確保が必要になる可能性があるため)。
一方で、縮小するだけなら通常noexceptなデストラクタを削除する要素数分呼び出すだけであるため、noexceptにすることができます。
この提案は、コンテナサイズの縮小専用のnoexceptな関数を追加することで、コンテナ縮小時のコード生成を改善しようとするものです。
提案では、vector, inplace_vector, list, forward_list, deque, vector<bool>に対して次のようなメンバ関数を追加することを提案しています。
constexpr void truncate(size_type sz) noexcept;
前述のように、これはコンテナサイズの縮小(切り詰め)専用の関数であり、sz個の要素だけを残します(削除する数を指定するものではない)。
.resize()ではなくtruncate()が使用されていることでコンテナサイズを切り詰めるという意図が明確になり可読性が向上するメリットがある他、デフォルトコンストラクタを持たない型に対する切り詰め操作も可能になります(.resize()の場合拡大時のパスでデフォルトコンストラクタを要求するためエラーになる)。
P3533R2 constexpr virtual inheritance
定数式で、仮想継承をしているクラス型を扱えるようにする提案。
以前の記事を参照
- P3533R0 constexpr virtual inheritance - WG21月次提案文書を眺める(2024年12月)
- P3533R1 constexpr virtual inheritance - WG21月次提案文書を眺める(2025年01月)
このリビジョンでの変更は、constexprコルーチン(P3367)に関する文言を削除したことです(この提案はC++26対象だがP3367はC++29対象なため)。
この提案は2025年6月の全体会議で承認され、C++26に採択されています。
P3537R1 Presentation on Concurrent Queue API
P0260の紹介スライド。
以前の記事を参照
このリビジョンでの変更は明確ではないですが、ページ数が13ページ増えており例や議論などが追加されています。
P3540R1 #embed Parameter offset
#embedにオフセットパラメータを渡せるようにする提案。
以前の記事を参照
このリビジョンでの変更はtypo修正と文言の修正などです。
P3544R0 ranges::to<view>
ranges::toが変換先としてviewを指定できない制約を取り除く提案。
ranges::to<C>(...)は変換先の型Cに対してviewではない事だけを要求しています。これによって例えば、分割文字列をstd::string_viewを要素とするコンテナに詰めていく様な使用法が阻害されています。
auto ints = "1.2.3.4"sv | views::split('.') | ranges::to<vector<string_view>>(); // error
ranges::toの入力範囲がrangeのrangeになっている場合、ranges::toは内部で内側の範囲に対して再帰的にranges::toを呼び、その際に入力の内側範囲がCの内側範囲に変換可能ではない場合(views::splitの内側範囲はstd::string_viewに暗黙変換できない)、ranges::to<range_value_t<C>>のように呼ぶためCもrangeのrangeになっている場合は内側の範囲もviewであってはなりません。
この例は内側のstd::string_viewがviewであるためにエラーになっています。ただし、次のようにCの内側の型を指定しなければ動作します
auto ints = "1.2.3.4"sv | views::split('.') | ranges::to<vector>(); // ok
この場合、入力の内側範囲はsubrangeが使用されているため、Cの内側範囲もsubrangeになることによって上手くいきます。ただし、この場合のsubrangeはviewのはずです。そこで同様に、ラムダ式を用いてCの内側範囲を指定しない形で呼び出すと動作するようになります
auto ints = "1.2.3.4"sv | views::split('.') | views::transform([](auto r) { return string_view(r); }) | ranges::to<vector>(); // ok
これは、ranges::to<vector>への入力範囲の内側範囲がstd::string_viewになることによって、推論される出力範囲の要素型(内側範囲)と一致することで変換可能になり、その際の処理パスではCの内側範囲型に対するviewの制約チェックが行われないためです。
そしてさらに、これと似た理由によって次のコードは動作してしまいます
auto ints = "1.2.3.4"sv | views::split('.') | ranges::to<vector<span<const char>>>(); // ok in the current standard!!!
これは、std::spanのrangeコンストラクタがexplciit指定されないことによって入力の内側範囲(views::splitの要素型)が出力の内側範囲(span<const char>)に変換可能になることで、同様にspan<const char>がviewであるというチェックがスキップされるためです。
文字列をsplit, slide, chunk, chunk_byなどのアダプタを使用して処理した結果をstring_viewのコンテナに入れることはかなり一般的なワークロードと思われるため、これらはもっと簡易に実行できる(最初のコードが動作する)必要があります。
そもそもranges::toのターゲット型がviewであってはならない理由を考えると、2つの理由がありそうです
- ユーザーが
viewからviewを作成できないようにするため - 安全性への懸念から
前者の場合、<range>ヘッダにあるview型については理に適っているかもしれません(アダプタを使わない理由が無いため)が、ranges::to<string_view>のようにstd::string_view/std::spanについてはあてはまりません。また、views::takeの代わりにranges::to<take_view>をわざわざやりたがる人もいないと思われるものの、禁止するほどの悪影響があるわけでもなさそうです。
後者の理由は説得力があります。実際、std::string_viewは右辺値文字列から構築できるため、単純に許可してしまうとranges::to<string_view>(string("abc"))の様な変換が可能になってしまいます(これはダングリング状態になる)。しかしこれは、入力範囲にborrowed_rangeを要求することで簡単に解決することができます。
この提案はranges::to<C>のCがviewであっても、入力範囲がborrowed_rangeであれば変換を許可するようにしようとするものです。ただし、この制約は単なるConstraints(SFINAE可能条件)ではなく、Mandates(満たさなければコンパイルエラー)にすることを提案しています。
入力範囲型をRとすると、range::to<C>のMandatesは次のようになります
CがCV修飾の無いクラス型であること- 次のどちらか
CがviewではないCがviewならば、Rがborrowed_rangeのモデルである
提案文書より、サンプルコード
auto sv1 = ranges::to<string_view>("abc"s ); // error auto sv2 = ranges::to<string_view>("abc"sv); // error -> ok array arr{...}; auto sp1 = ranges::to<span<int>>(std::move(arr)); // error auto sp2 = ranges::to<span<int>>(arr); // error -> ok auto take = views::iota(0) | ranges::to<ranges::take_view>(5); // error -> ok, CTAD via ranges::to, but meh auto drop = vector<int>{...} | ranges::to<ranges::drop_view>(5); // error auto ints = "1.2.3.4"sv | views::split('.') | ranges::to<vector<string_view>>(); // error -> ok int numbers[] = {...}; auto groups1 = numbers | views::slide(3) | ranges::to<vector<span<int>>>(); // ok auto groups2 = numbers | views::slide(3) | ranges::to<vector<span<int, 3>>>(); // error -> ok, recursively via ranges::to auto views = vector<int>{...} | views::transform([](int x) { return to_string(x); }) | ranges::to<vector<string_view>>(); // ok, but dangling(変換なし
この例において、末尾のコメントでerror -> okとなっているところだけがこの提案によって許可される部分で、それ以外は変化のない部分です。
この提案はC++23へのDRとすることが提案されており、SG9では合意されています。
P3547R1 Modeling Access Control With Reflection
クラスメンバのリフレクションにおいて、アクセスコンテキストを明示的に指定するようにする提案。
以前の記事を参照
このリビジョンでの変更は
is_accessible()は現在定義中のクラスのメンバを照会する際にエラーとなるaccess_context::current()は関数の仮引数スコープから呼び出された場合にその関数によるコンテキストを返さない
などです。
P3552R1 Add a Coroutine Task Type
std::executionに対応したコルーチンlazy型の提案。
以前の記事を参照
このリビジョンでの変更は
- SG1のフィードバックにより、名前を
lazyからtaskへ変更lazyを選択した理由のセクションを追加
any_schedulerをtask_schedulerに変更taskクラスの文言を追加
などです。
P3556R0 Input files are source files
規格中の入力C++ソースファイルに関する用語を整理する提案。
現在のC++規格文書中では、入力ファイルを指す言葉としてinput fileとsource fileという2修理の用語が使用されています。しかし、source fileはその定義がなされているのに対して、input fileは明確な定義がされないままP2995R6にて導入されたようです。
この2つの言葉の間には何かしらの関連性が定義されているわけではないが、使用法から見るにinput fileはsource fileの部分集合になっているようです。
このような状況の修正のため、この提案ではinput fileという言葉の使用を廃止して、source fileに統一しようとしています。
さらに、統一後のsource fileという言葉も、物理的なファイルの内容を指している場合と、そこからプログラムテキストを読み取ってコピーしコンパイラによって保持されているものを指している場合の2つの使われ方があります。前者はコンパイラによって更新されるべきではない不変のものであり、コンパイラは翻訳フェーズ2以降では後者のコピーしたものを適宜編集しながらコンパイルを行っていくことになります(提案では、両者の違いを画像をsource fileとして扱う処理系がwell-formedであるはず、という主張によってこれを説明しています)。
そのためこの提案では、統一後のsource fileという言葉の使用をさらに2種類に分け、ファイルから読み取った内容を保持するコピーの意味で使用されているsource fileという用語をsource textに置き換えることを提案しています。
source fileの定義はすでになされており、source textの定義は「翻訳フェーズ1終了時に生成される翻訳文字集合の要素のシーケンス」として定義します。
どうやら、この変更によってC++コンパイラの入力(source file)として正しいものは必ずしもテキストファイルだけではなく、ソースコードを写した画像のようなものもカバーされることになります。
P3557R1 High-Quality Sender Diagnostics with Constexpr Exceptions
std::executionにおける、エラーメッセージ出力を改善する提案。
以前の記事を参照
このリビジョンでの変更は
- 直前の不完全な編集の影響を受けていた
std::execution::get_completion_signaturesの仕様を修正 - 誤って削除されていた
get_completion_signaturesのawaitablesサポートを復帰 transform_completion_signaturesの代替案を変更し、停止した完了シグネチャのcompletion_signaturesオブジェクトではなく変換関数を受け取るようにしたimpls-for<Tag>::check-typesのカスタマイゼーションポイントに不足していた意味論制約を追加basic-sender<Tag>::get_completion_signaturesに不足していた構文制約を追加std::execution::connectのMandatesを強化stopped_as_optional.transform_sender(sndr, env)の制約を修正let_*, schedule_from, into_variant, split, when_allの各アルゴリズムにおいて、先行処理の結果を中間領域にコピーできない場合に型エラーを報告する- あれば便利(nice-to-have)として提案されている機能の文言を追加
eptr_completion_ifmake_completion_signaturestransform_completion_signatures(constexpr function version)invalid_completion_signature
- Githubリポジトリで報告されたいくつかのIssueについての修正案を統合
- 段落番号の修正
などです。
P3558R1 Core Language Contracts By Default
未定義動作のContractsによるハンドリングを将来のC++のデフォルトにする提案。
以前の記事を参照
このリビジョンでの変更は
- 更なる懸念事項について詳細化
- P3599R0から導入する代替案を追加
などです。
この提案はC++26へプロファイル導入を間に合わせようとする動きを受けて、重複する将来像を持っているContractsを考慮すべきとする立場から書かれたものであり、C++26へプロファイルを導入しないことになったため、ひとまず現時点での追及は停止されたようです(29以降の機能としてプロファイルと一体で検討されていくようです)。
P3561R1 Index based coproduct operations on variant, and library wording
std::variantに対してインデックスに基づくvisit()操作を追加する提案。
以前の記事を参照
このリビジョンでの変更は、valueless_by_exception() == true時の問題についてを追記したことです。
P3568R1 break label; and continue label;
名前付きループにより、ネストしたループからの脱出の簡易な構文をサポートする提案。
以前の記事を参照
このリビジョンでの変更は
- N3377の構文案を完全に考慮しなくなった
- C++で独自の構文を選択することを回避し、WG14でもN3377がリジェクトされたため
- 提案する文言の改善
- 機能テストマクロの追加
などです。
P3570R0 optional variants in sender/receiver
並行キューのasync_pop()の最適な戻り値型を探る提案。
P0260R13で提案中の並行キュークラスは、そのレビューの中で.async_pop()の戻り値型についてが議論の的になっているようです。それは、.async_pop()がコルーチンとしてもsenderとしても使用でき使用されることが想定されていて、その際の使用パターンに若干の違いがあるためです。
// コルーチンでの使用パターン auto coro_grep(stdx::coqueue<std::fs::path>& file_queue, std::string needle) -> stdp::task<void> { while (auto fname = co_await file_queue.async_pop()) { grep_file(*fname, needle); // queue has data } // queue closed co_return; } // std::executionでの使用パターン stdexec::sender auto sr_grep(auto scheduler , stdx::coqueue<std::fs::path>& file_queue, std::string needle) { return stdexec::repeat_effect_until( stdexec::starts_on(scheduler, files.async_pop() | stdp::overload( []() -> bool { return true; }, // queue closed [needle](std::fs::path const& fname) -> bool { // queue has data return grep_file(fname, needle); }); )); }
.async_pop()自体はsenderを返しますが、そのsenderの完了シグネチャ(set_value()チャネルの型)が問題となります。コルーチンの使用パターンの場合、その完了シグネチャはset_value_t(std::optional<T>)となる必要があります。一方std::executionの場合、set_value_t(), set_value_t(T)となる必要があります。どちらを選択したとしても、もう一方のパターンの使用方法が妨げられます。
この提案は、この2つの使用パターンの両方を満たすことのできるような.async_pop()の戻り値型の実現可能性を探るものです。そして、この提案ではこの解決策として大まかに次の3つの3ことを挙げています。
- カスタム
awaiterの利用 - 汎用的な値の変換
- a1: 常に変換する
- a2: オプトアウト
- b: オプトイン
オプション1は、execution::as_awaitableのカスタマイゼーションポイント(senderをコルーチンのawaitable変換するもの)を利用して、co_awaitされた場合に独自のカスタムawaiter型を返すようにする方法です。これは実装が簡単で両方の場合で理想的なインターフェースを提供できる方法ですが、これによる.async_pop()が返すsenderだけがコルーチンで使用でき、任意のアダプタを介すとその能力が失われます。
オプション2は、execution::as_awaitableによる変換プロセスに介入して、単一値完了シグネチャをコルーチンのawaitableに変換する際に、その直後にもう一段の変換を行うことによって別の変換先へと変換します。このアプローチはP3552R0でも検討されており、そこでinto_optional()として挙げられていた変換アダプタを採用します。
この上で、into_optional()をどう適用するかによってさらに3つの選択肢があります。
a1(常に変換)は、as_awaitable内部にinto_optional()適用を組み込むことでデフォルトで常に変換するようにします。互換性があれば、任意のsenderがコルーチンでより使用しやすくなりますが、ユーザーがこの変換をカスタマイズすることができません(例えばinto_variant()等を使用できない)。
a2(オプトアウト)は、a1同様にデフォルト動作として組み込むものの、senderの環境を通じてget_await_completion_adapterプロパティをfalse_typeで伝播することでこの変換をオフにできます。a1の利点を享受しつつ欠点を補うことができるものの、環境をセットアップしない場合自動で変換されてしまうため問題がある場合があります。
b(オプトイン)はa2とは逆に、デフォルトではこの変換をオフにしつつ、get_await_completion_adapterプロパティが伝播している場合にオンにするものです。なおかつ、変換の方法はget_await_completion_adapterクエリの結果によって制御することができ、into_optionalに固定されません。a1の利点を享受しつつa1/a2の欠点を補えますが、利用するにはオプトインが必要となるため少し面倒さがあります。
この中から、この提案としては2-bのオプトインによるものを提案しています。
オプション2-bの場合のsender型におけるオプトイン環境定義例
struct env { auto query(get_await_completion_adapter_t) const -> into_optional_t { return {}; } }; auto get_env() const noexcept -> env { return {}; }
提案のapendixには、ここで提案しているものの実装や、並行キューにおける利用例の実装などが記載されています。
- P0260R13 C++ Concurrent Queues - WG21月次提案文書を眺める(2024年12月)
- P3552R0 Add a Coroutine Lazy Type - WG21月次提案文書を眺める(2025年01月)
std::execution::as_awaitable- cpprefjp- P3570 進行状況
P3579R1 Fix matching of non-type template parameters when matching template template parameters
テンプレートテンプレートの特殊化のマッチング時に、NTTPの縮小変換を許可しないようにする提案。
以前の記事を参照
このリビジョンでの変更は
- 半順序に関するセクションの追加
- 文言の改善
などです。
P0522R0の影響によるこの問題はNTTPを含めた場合のテンプレートの半順序にも影響しているようです
template<template<short> class TT1> void f(TT1<0>); // #1 template<template<int> class TT2> void f(TT2<0>); // #2 template<int> struct B; template void f<B>(B<0>); // selects #2(P0522R0環境では曖昧になる
P0522R0ではint -> shortの縮小変換も考慮されるようになってしまったことによって#1も候補として残り曖昧になりますが、この提案による修正によってこれは正しく#2を選択するようになります。
EWGのレビューと投票ではこの提案をDRとすることに合意がされています。
P3589R1 C++ Profiles: The Framework
フレームワークとしてのプロファイル機能の概説文書。
以前の記事を参照
このリビジョンでの変更は
- プロファイルの使用例を追加
- SG23/EWGに提出された過去の提案への参照を追加
- プロファイルの指定には引数が含まれることを明確化し例を追加
- 理由メッセージとプロファイル名指定による
profiles::suppress()の例を追加 - guaranteed profilesとrequested profilesの例を追加
- 提案する文言を書き直し
などです。
P3591R0 Contextualizing Contracts Concerns
最近提起されたContarcts MVPに対する懸念について応える文書。
この文書は、前月(2025年1月)に公開されたP2900のContractsに反対する2つの文書P3573とP3506の提起する懸念に応えるものです。
これらの提案の内容については以前の記事を参照
- P3573R0 Contract concerns - WG21月次提案文書を眺める(2025年01月)
- P3506R0 P2900 Is Still not Ready for C++26 - WG21月次提案文書を眺める(2025年01月)
これらの提案で提起されている懸念の大きなものは次の6つです
const化- 契約条件からの例外のキャプチャ
- 仮想関数の契約の評価についての複雑さ
- 全体的な設計の不安定さ
- 実装定義の多さ
- 実装経験の乏しさ
これらに加えて追加でいくつかの懸念点が挙げられており、この提案ではそれに対して回答を行っています(ここではそれを転載しません)。
特に、これらの懸念点がすでにSG21/EWGで十分に議論され、合意済みの事項であること、必要ならP2899でそれに関連する議論について確認することができることを強調するとともに、これらの懸念点をすべて完全に解消することは不可能であることを指摘しています(様々なトレードオフがあり、標準機能の観点から現在の設計が選択されている)。
この文書の結論としては、P3573とP3506で提起されている懸念点は既に考慮したうえで一定の合意を得て解決済みであり、P2900R13をC++26に採択することを妨げるものではないことを強調しています。
P3592R0 Resolving Concerns with const-ification
契約注釈内での変数のconst化についての懸念を緩和するための提案。
P2900で提案中のContractsでは、契約注釈内から参照されるローカル変数等が暗黙的にconst化されます。これは契約述語を介した副作用の影響を低減するためのものですが、C++の他の場所との一貫性がないことなどから懸念する声がまだあります。
例えば、同じ式でも契約注釈内とその後の関数本文内で意味が変わる場合があり得ます。
struct X { bool is_const() { return false; } bool is_const() const { return true; } }; void g(X& x) pre( x.is_const() ) // constオーバーロードが呼ばれる { // 非constオーバーロードが呼ばれる if (x.is_const()) { // This branch is never taken. } }
逆に、契約注釈内と同じセマンティクスで述語を表現する簡単な方法が用意されていない点も問題となっています。
契約注釈内であえて非constな変数を使用したい場合にも簡易な方法がなく、一般的に使用が忌避されるconst_castを使用する必要があります。
// legacy API struct X; bool check_valid(X& x); // 引数を変更しないがconstを忘れている void f(X& x) pre(check_valid(x)); // ill-formed void g(X& x) pre(check_valid(const_cast<X&>(x))); // OK
これらの問題は既存のコードに存在しているものと思われるため、このようなコードをContractsへ移行使用とする際のブロッキング要因になってしまいます。
この提案では、このような懸念を解消するための3つの機能の追加提案を行っています
- 契約注釈内と同じ意味の術語をその外で再現するための
contract_predicate(expr)演算子の追加contract_predicate内部の式は契約注釈内と同じconst化が行われる
- 局所的に
const化を無効化するためのnoconst演算子の追加- 契約注釈内のid式に指定して、その変数に対する
const化を解除する
- 契約注釈内のid式に指定して、その変数に対する
- 契約注釈の
const化を無効化するためのmutable指定の追加pre mutable (pred)のように使用する
contract_predicateは契約注釈内でしか得られないconst化を他の場所他の式に対して再現するものです。
struct X { bool is_const() { return false; } bool is_const() const { return true; } }; void g(X& x) pre( x.is_const() ) // constオーバーロードが呼ばれる { // constオーバーロードが呼ばれる if (contract_predicate(x.is_const())) { // This branch is never taken. } }
提案では述語のみならず任意の式に対して適用可能で、contract_predicate式の型と値カテゴリは指定された式(const化後の)の型と値カテゴリを持つようにすることを提案しています。
contract_predicateという名前はキーワードにすることを提案しています。Githubでの検索では使用例は見つからなかったようです。
代替の提案として、contract_predicateを採用したうえで契約注釈のconst化を有効にするために、contract_predicateの指定を必須にすることを提案しています。
int f(const int x) pre contract_predicate (x != 1) // a precondition assertion post contract_predicate (r : r == x && r != 2) // a postcondition assertion { contract_assert contract_predicate (x != 3); // an assertion statement return x; }
この場合、contract_predicateの指定が必須となる(提案では外した状態を提案していない)ため煩わしさがかなり増すものの、短い代わりのキーワードの捜索は困難としています。
noconstは契約注釈内で使用して、const化を解除するためのものです。
struct X { bool is_const() { return false; } bool is_const() const { return true; } } void f(X& x, const X& y) pre( x.is_const() ) pre( y.is_const() ) pre( !noconst(x).is_const() ) // type of noconst(x) is X pre( noconst(y).is_const() ) // type of noconst(y) is still const X pre( ![]() { X z; return z.is_const(); }()) pre( ![]() { X z; return noconst(z).is_const(); // error: zはconst化の対象ではない }());
noconst演算子は契約注釈内でのみ使用できます。
3つ目のmutable指定は、契約注釈自体のcosnt化を無効化するための追加の指定です。
struct X { bool is_const() { return false; } bool is_const() const { return true; } } void f(X& x) pre(x.is_const()) pre mutable (!x.is_const()) {}
mutable指定された契約注釈内では、id式の結果がconst化されなくなります。ただ、指定するキーワードの選択には異論が出ているようです(ラムダ式のmutable指定と意味が若干異なり、付与された対象が変更可能になるわけではないため)。
提案1と2は実装経験がありませんが、提案3はGCCにおいて実装経験があります。
この提案は結局P2900R14(C++26最終版)には導入されずにクローズされています。どうやら、この提案抜きでも一定のコンセンサスを得ることができたようです。
P3599R0 Initial Implicit Contract Assertions
暗黙の契約アサーション機能の初期セットの提案。
暗黙の契約アサーションとは、P3100R1で提唱されたコア言語中の未定義動作に繋がりうる操作について、暗黙的に事前/事後条件を持つものとして扱うことで、実行時の未定義動作ハンドリングをContractsフレームワークによって行おうとするものです。暗黙の契約アサーションは、プログラムコード中にそのアサーションに対応するコード表現が存在しないという点を除いて、ユーザーが記述可能な契約アサーション(明示的な契約アサーション)とほとんどすべての点において同一の扱いとなります。
P3100については以前の記事を参照
この提案は暗黙の契約アサーションを言語に導入するための最初のステップとして、その最小サブセットとなる機能と対象のコア言語未定義動作の初期セットを提案するものです。
提案しているセマンティクスに変更はなく、ここではまだ自動フォールバック動作(整数オーバーフローをラップアラウンドや飽和演算などで処理する)を導入していないため、P3100で提案されているassumeセマンティクスはまだありません。
各セマンティクスの動作は次のようになります(通常の契約アサーションと変わりありません)
- quick enforce: 診断メッセージの出力や違反ハンドラ呼び出しな度を行わずにすぐ終了する
- enforce: 診断メッセージの発行後、プログラムを終了する
- これをデフォルトとすることを提案している
- ignore: これまでと同様の動作
- observe: 診断メッセージを発行して、プログラムを継続する
- 契約アサーション自体がobservable checkpointになっているため、UB起因のタイムトラベル最適化で削除されない
ユーザー定義の違反ハンドラのサポートも通常通り可能であり、enforce/observeセマンティクスの場合に呼び出されます。その際、kindプロパティはimplicit、detection_modeがUBに応じた列挙値(後述)になります。
評価セマンティクスの選択も通常通り実装定義(コンパイラオプションを想定)とされます。
この提案で暗黙の契約アサーションを挿入する対象としている操作は次のものです
- 組み込みの配列添字演算子
- 配列引数の境界が既知であり
N、実行時インデックス引数がxであるとき - 暗黙の事前条件として、
0 <= x && x < Nを持つ - 違反した場合の
std::contracts::detection_modeはboundsになる
- 配列引数の境界が既知であり
- 組み込みの間接参照演算子
- ポインタ引数を
pとして、暗黙の事前条件p != nullptrを持つ - 違反した場合の
std::contracts::detection_modeはdereferenceになる
- ポインタ引数を
- 符号付整数の算術演算
- その型の範囲内の値を生成するという事前条件を持つ
これらは初期セットであり、現在確実に検査可能と思われるもののうちの最小限のものです。将来的にこのセットは拡張され、実行時UBのさらに多くのものを補足可能になることが想定されます。
この提案が採択されると、次のようなコードは
int main(int argc, char *argv[]) { int a[10] = { /* ... */ }; std::size_t i = (argc > 1) ? std::atoi(argv[1]) : 0; // argv[1]に10以上の値がセットされているとUB return a[i]; }
次のようなコードと等価になります
int main(int argc, char *argv[]) { int a[10] = { /* ... */ }; std::size_t i = (argc > 1) ? std::atoi(argv[1]) : 0; // 暗黙の契約アサーションが挿入される contract_assert( i < (sizeof(a) / size(*a)) ); return a[i]; }
また、この提案およびP3100の内容はプロファイル機能の実行時検査を行う部分と重複や衝突があります。ここでは、プロファイル機能の実行時検査の部分はこの提案やP3100の方向性に統一して、プロファイル機能は静的検査に制限する事を提案しています。
この提案は機能を最小のサブセットに限定することでC++26への導入を目指していました。どうやら、重複するプロファイル機能がC++26への導入を急いでいたことを受けて急いでいたようで(重複する部分があるためプロファイル機能が先に入ると影響がある)、プロファイル機能がC++26への導入を急がない(ホワイトペーパーの仕組みを利用する)事になったことを受けてこちらの提案もC++29以降を目指すことになったようです。その検討はP3100で行われるためこの提案は一旦クローズになっています。
P3603R0 Consteval-only Values and Consteval Variables
consteval変数の提案。
C++26にはコンパイル時にのみ存在が許されている値というものが、定式化されてはいないものの2種類存在しています。
consteval関数の関数ポインタ/参照std::meta::infoオブジェクト
consteval int add(int x, int y) { return x + y; } // consteval関数ポインタそのものは存在するものの、永続化できない constexpr auto ptr = add; // error // meta::infoオブジェクトも永続化できない constexpr auto refl = ^^int;
これら2つのものは、どちらも同じように永続化(実行時に持ち越すこと)出来ないようになっていますが、規格におけるその禁止の仕方はかなり異なっています。
consteval関数の関数ポインタ/参照- “permitted result”と呼ばれていたルールを使用して、
ptrの使用を禁止する- “permitted result”: 定数式で許可されること(あるいはしてはいけないこと)を列挙したルール
- “permitted result”と呼ばれていたルールを使用して、
std::meta::infoオブジェクトreflの宣言そのものは許可されるが、constevalのみの型と即時エスカレーションによって、reflを含むコンテキストが必ず定数式内であることを保証する
このような同じ要件を指定するために異なる規則・規定を使用している現状は、規定が複雑になるとともに文章に重複が生じており、双方の一貫性を確保し続けるのに保守コストがかかります。実際、consteval関数ポインタは定数式内では使用できるもののconstexpr変数には入れられないという差異が生じています(consteval関数内であればconstexpr無しの変数には入れられる)。
std::meta::infoの場合は型だけでそれが定数式のみ使用可能か分かりますが、consteval関数ポインタはあくまでただの関数ポインタであるため型だけからは判断できません。
この提案ではます、定数式でのみ使用可能な値という概念を定式化して使用することで、このような規定の重複・並立・複雑化を解消しようとしています。
そのためにまず、consteval変数を新たに導入します。consteval変数はコンパイル時にのみ存在可能な変数であり、その使用は全て定数式である必要がある変数です。
consteval int add(int x, int y) { return x + y; } constexpr auto p1 = add; // ng consteval auto p2 = add; // ok int main(int argc, char**) { return p2(argc, 1); // ng、`p2`はconsteval変数であり、その使用は定数式でなければならない // main()は即時エスカレーションしないため、ここは定数式ではない }
現在このp2の様な変数を取る方法はありませんが、これによってそれが提供されるようになります。また、consteval変数は実行時に必ず参照されないため、実行時に余分な領域を占有しません。constexprは必ずしもそれが保証されていないので、consteval変数には単体で便利なものです。
このp1とp2の初期化式の振る舞いの際を定義するために、constevalのみの値を明確化します。式がconstevalのみの値を持つとは、次のいずれかの場合となります
- 式のいずれかの構成要素が、
consteval変数を指しているか参照している - 式のいずれかの構成要素が、
consteval関数を指しているか参照している - 式のいずれかの構成要素が、
constevalのみの型である
consteval変数を初期化できるのは任意の定数式ですが、constevalのみの値で初期化できる変数はconsteval変数となります(前述のように、定数式内では普通に使用可能です)。
constevalのみの値の概念は、関数/式の即時エスカレーションの規定のために使用できる便利な概念です。特に、P3496R0で提案されている式の即時エスカレーションのために使用可能です。
さらに、これらのconsteval変数/constevalのみの値を用いることで、LWG Issue 4197で報告されている既知のイシューを解決することができます。LWG Issue 4197のイシューは、constevalラムダ式をstd::variantのvisit()で使用しようとするとコンパイルエラーになるバグレポート(libc++/libstdc++)からのもので、consteval関数の関数ポインタをコンパイル時テーブルに保存することができないために起きているものです。この制限によって、std::visit()の定数時間での関数呼び出しの要件を満たす実装が不可能になると報告されています。
variantの簡易実装と疑似再現コードで書くと、次のようなことが起きています
#include <array> template <class T, class U> struct Variant { union { T t; U u; }; int index; constexpr Variant(T t) : t(t), index(0) { } constexpr Variant(U u) : u(u), index(1) { } template <int I> requires (I < 2) constexpr auto get() const -> auto const& { if constexpr (I == 0) return t; else if constexpr (I == 1) return u; } }; // visit()呼び出しを定数時間で解決するためのvtable template <class R, class F, class V0, class V1> struct binary_vtable_impl { template <int I, int J> static constexpr auto visit(F&& f, V0 const& v0, V1 const& v1) -> R { // ここでfが呼び出されていることによって、この関数は即時エスカレーションされconsteval関数となる return f(v0.template get<I>(), v1.template get<J>()); } // テーブルの初期化処理 static constexpr auto get_array() { return std::array{ std::array{ &visit<0, 0>, // consteval関数のポインタを取っている &visit<0, 1> }, std::array{ &visit<1, 0>, &visit<1, 1> } }; } // テーブル本体の静的constexpr変数 static constexpr std::array fptrs = get_array(); // consteval関数のポインタをconstexpr変数に保存しようとしていることでエラーが起こる }; // 簡易variantのvisit()実装 template <class R, class F, class V0, class V1> constexpr auto visit(F&& f, V0 const& v0, V1 const& v1) -> R { // 2次元のテーブルで呼び出す関数を引くことで定数時間で呼び出し先を解決する using Impl = binary_vtable_impl<R, F, V0, V1>; return Impl::fptrs[v0.index][v1.index]((F&&)f, v0, v1); // ng } consteval auto func(const Variant<int, long>& v1, const Variant<int, long>& v2) { // constevalラムダでvisit()を呼ぶ return visit<int>([](auto x, auto y) consteval { return x + y; }, v1, v2); } static_assert(func(Variant<int, long>{42}, Variant<int, long>{1729}) == 1771);
これは実際のstd::variantとstd::visit()実装の簡易な再現コードであり、非現実的なコードではありません。
とはいえ、consteval変数/constevalのみの値を直接用いただけではこの問題を解決できません。提案では、consteval変数への昇格という仕組みよってこれを解決しようとしています。
上記コードはconstevalのみの値を持つget_array()の結果を用いてstatic constexpr変数を初期化しようとしていることで起きています。例えば、このコードを動かすためだけであれば、static constexpr変数がstatic consteval変数になれば解決します。とはいえ、そうすると今度はふつうのラムダ式などを渡した際に動作しなくなります。
そこで、初期化式がconstevalのみの値を持つ式であるstatic constexpr変数をconsteval変数に自動でエスカレートする、という仕組みを導入します。この例の場合
// 簡易variantのvisit()実装 template <class R, class F, class V0, class V1> constexpr auto visit(F&& f, V0 const& v0, V1 const& v1) -> R { // 2次元のテーブルで呼び出す関数を引くことで定数時間で呼び出し先を解決する using Impl = binary_vtable_impl<R, F, V0, V1>; return Impl::fptrs[v0.index][v1.index]((F&&)f, v0, v1); // ok。consteval変数`Impl::fptrs`の使用により、この関数はconsteval関数へエスカレートする }
consteval変数エスカレーションによって、Impl::fptrsはconsteval変数になっています。consteval変数が使用されているconstexpr関数は即時エスカレーションの対象であり、暗黙的にconsteval関数となるため、このコードは問題なく動作するようになります。もちろん、非constevalラムダを渡した時(実行時)でも動作します。
この修正は何より、ライブラリの変更を必要としません。
結局この提案では
constevalのみの値(consteval-only value)の概念の導入consteval変数の導入- 特定の
constexpr変数(constevalのみの値を持つ変数)を、consteval変数にエスカレートできるようにする
の3点を提案しています。
P3605R0 isqrt: A function to calculate integer square root of the nonnegative integer
非負整数の整数平方根を計算するためのisqrt関数の提案。
ここで提案されているisqrt()は、非負の整数に対してその平方根以下の最大の整数を返すような平方根計算を行うものです。数学的には次のように定義されます
$$ isqrt(n) = \lfloor \sqrt{n} \rfloor = max { k \in N: k2 \leq n }, for \space n \in N, where \space N = { 0, 1, 2, 3, ...} $$
このような計算は数論アルゴリズムで頻出する(素数判定や因数分解、暗号アルゴリズムなど)ものの、浮動小数点数の扱いによって正しい実装が難しいという問題があります。
このisqrt()の結果が欲しい場合によく使用されるuintmax_t(sqrt(n))という方法は、小さな整数値に対しては正しいものの大きな整数値(仮数部のビット数が3桁以上)に対して不正確な結果を返します。これは、nの値がdouble型で正確に表現できる場合でも、sqrt(n)の結果が浮動小数点数の精度限界により、真の平方根に最も近いdouble値として丸められるためです
例えば
$$ n = 671088652 = 4503599761588224 = 252 + 227 $$
この値はdouble型で正確に表現でき、nの平方根は次のようになります
$$ \sqrt{n} = \sqrt{4503599761588224} = 67108864.9999999925494195… $$
先ほどの定義によるisqrt(n)はこの値の小数点以下を切り捨てたものになります
$$ isqrt(n) = \lfloor \sqrt{n} \rfloor = \lfloor \sqrt{4503599761588224} \rfloor = \lfloor 67108864.9999999925494195… \rfloor = 67108864 $$
この$\sqrt{n}$はdouble型で正確に表現できないため、sqrt(n)の結果はdouble型で表現可能な最も近い値を丸めによって返します。$\sqrt{n}$に隣接する2つのdouble値は次の2つです
$$ 67108865-2^{-26} = 67108864.99999998509883880615234375 < \sqrt{n} < 67108865 $$
| 値 | $|value-\sqrt{(n)}|$ |
|---|---|
67108864.99999998509883880615234375 |
$7.4505807079461285 \times 10^{-9}$ |
67108865.0 |
$7.4505804859015277 \times 10^{-9}$ |
67108865.0の方が$\sqrt{n}$の真値に近いため、sqrt(n)の結果はこの値に丸められます。よってuintmax_t(sqrt(n)) = 67108865になります。
より一般に、整数$i$に対して$n = i2 -1$となるような整数$n$に対して、この問題が発生します。この例の4503599761588224はそのようなnの最小のものです(double型において)。
long double型が80ビットの浮動小数点数型として実装されていればこの問題は解消されるものの、int128_tのようなより幅の広い整数型が追加されると同様の問題が発生するため、より広い浮動小数点数型を使用するだけではこの問題を解決できません。
isqrt()という命名については、sqrt()のオーバーロードが追加できない(既に整数型に対するオーバーロードが存在しているため)ことやISO/IEC 10967-2:2001規格に準拠した命名であることからこの名前を提案しています。
// 提案している宣言 namespace std { template<class T> constexpr T isqrt(T n) noexcept; }
また、isqrt()は非負整数だけを引数に取るものの、冗長なキャストを回避するために、関数テンプレート自体は任意の整数型を受け取れるようにすることを提案しています。引数が正であることは関数の事前条件とされます。
P3606R0 On Overload Resolution, Exact Matches and Clever Implementations
関数テンプレートを含めた関数オーバーロードの解決において、GCCの実装戦略を標準化する提案。
次のようなコードにおいて
template<typename T> decltype([] { return T::x;}) f(T); // #1 void f(int) {} // #2 int main() { f(0); }
GCCはf(0)の呼び出しにおいて完全にマッチしている#2を選択し、#1のインスタンス化を行いません。一方その他の実装ではまず#1のインスタンス化を先に行うためエラーになります(戻り値型のdecltype内のラムダ式内部のT::xがエラーになるものの、ここは即時コンテキストではないためハードエラーになる)。
すなわち、GCCは関数テンプレートが含まれるオーバーロード解決において候補の中に全ての引数に対して完全にマッチする候補が存在する場合、テンプレート候補は一切考慮されずインスタンス化も発生しません。
この挙動は標準の 13.9.2 [temp.inst]/9 にある
If the function selected by overload resolution can be determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
の解釈によって許可されている振る舞いではあるものの、CWGの見解としては文言そのものには準拠していないようです。
この振る舞いは一方で、非即時コンテキスト(SFINAEしないコンテキスト)におけるエラー診断をしないということでもあります。しかし、別の例を見てみると
struct S { template <typename T> requires std::copyable<T> explicit S(T op) noexcept; // #1 S(const S&) noexcept = default; // #2 }; static_assert(std::copyable<S>);
この例においてSがcopyableであるかを調べるには、S(declval<const S&>())が有効な式であるかをチェックする必要があります。そのためにはT = Sとして#1をインスタンス化して、#1と#2の間でオーバーロード解決を行う必要があります。しかし、#1は再びstd::copyable<S>で制約されています。すなわち、Sがcopyableであるかを調べるには、まずSがcopyableであるかを調べる必要があります。このような制約の再帰はill-formedとなります。
しかし、GCCは先ほどと同じ理由によって#2を選択し、#1はインスタンス化も発生しません。このように、再帰を引き起こすコンセプトの制約チェックについては、非即時コンテキストのエラー診断を考慮しなくても、GCCの最適化の恩恵が明確になります。
これはこの提案のモチベーションの一つです。
もう一つは、CWG2369をclangで実装するためにこの実装戦略が必要となったためです。
CWG2369は、SFINAEとコンセプトによってテンプレートのインスタンス化結果が異なることがあるのを修正するために、テンプレート引数の置換と制約チェックの順序を逆にしようとするものです。
次のようなコードにおいて
template <typename U> struct B { static_assert(false); }; template <typename T> requires (sizeof(B<T>) == 1) void f(T, typename T::foo = 0) {} // #1 void f(int) {} // #2 f(0);
GCCは前述のように、#2を選択し#1はインスタンス化されません。
Clang(CWG2369実装前)では、#1をインスタンス化しようとしてまず引数のT::fooの置換を行い、int::fooが有効ではないためSFINAEにより#2が選択されます。
結果として起こる事は同じであっても、ClangとGCCでは異なる理由でそれが起きています。そして、CWG2369を実装すると置換の前に制約チェックを行うため、#1の制約式内のB<int>の定義内static_assertでハードエラーを起こし、コンパイルエラーとなります(GCCは変わらない)。
したがって、Clangにおいては後方互換性の観点から、CWG2369を実装することができなくなっています。
ClangにおいてCWG2369を実装するためにはGCCの実装戦略を取り入れる必要があり、そのためにはその実装戦略が規格に準拠したものであることを確認する必要があります。この提案はそのために提出されたものです。
GCCの動作を採択することにはいくつかの利点があります
- オーバーロード解決時の作業量を軽減させられるため、コンパイル時間を減らせる
- CWG2369の採用による影響を軽減できる
- テンプレートコンストラクタに
same_as制約を忘れる- 2つめの例のGCC以外での回避策
一方欠点は、テンプレート候補の即時コンテキストではない部分のエラーが診断されなくなる点です。これが許容可能かどうかは判然としておらず、この提案はその確認も兼ねています。
そして、GCCのこの実装戦略もまたCWG2369の採用による影響を軽減しようとするものだったようです。
なお、ここで挙げているものも含めて、提案文書にあるサンプルコードは実際のバグレポートから収集されたものを単純化したものです。したがって、これらの問題は実際出会わないようなコードで起こるだけのものではありません。
P3608R0 Contracts and profiles: what can we reasonably ship in C++26
プロファイル機能や暗黙の契約アサーションに関連する機能のC++26リリースを延期することを推奨する提案。
この提案では斬新なアイデアについてC++29自体をターゲットとするか、C++29以前にリリースされるホワイトペーパーに先送りにすることを提案するとともに、次のものについてはC++26に導入することを提案しています。
- 汎用プロファイルフレームワーク(P3589)
- 標準ライブラリの堅牢化(P3471)
- 標準ライブラリの堅牢化を有効にし、堅牢化された事前条件違反が発生した場合に無条件でプログラムを終了させるだけの具体的なプロファイル
- C++26時点では追加の柔軟性を提供しない
- 実装ベンダに対しては、将来的に他の違反処理方法を有効化する可能性を閉ざさないように推奨する
斬新なアイデアとはどうやら、暗黙の契約アサーションに関するContracts関連の機能提案や、より具体的な安全性プロファイルの提案の事を指しているようです。
その理由としては、どちらのものにも未解決の問題や合意が得られていない部分が存在しているため、締切に終われて未完成の機能をユーザーに押し付けることを避けるべき、としています。
プロファイルと契約の間にある重複・衝突しうる部分についてはさらに検討を進めて問題を解消し、コンセンサスを改善したうえで、全ての機能が一貫した全体として動作するようになってからリリースすべき、と指摘しています。
P3611R0 Dealing with pointer errors: Separating static and dynamic checking
ポインタのエラーに関する安全性を確保するための仕組みをC++26に導入する提案。
この提案では、静的検査と動的検査を一つのソリューションで担うのではなく、それぞれ別の現在利用可能なソリューションで対応することによってC++26でポインタのエラーにある程度の対応をしようとしています。ポインタのエラーとは、無効なポインタのデリファレンスと配列外参照を指しています。
- 動的検査: 標準ライブラリの堅牢化(P3471)
- 静的検査: type/boundsプロファイル(P3038、P3274など)
動的検査によって実行時のエラーを検出し(スーパーセット化)、静的検査によってポインタのエラーに繋がる操作を禁止(サブセット化)することで、ポインタのエラーに関する安全性を確保しようとしています。
この提案がどうなったのかはよく分からないのですが、C++26に対しては標準ライブラリの堅牢化が導入され、プロファイル関連の機能についてはホワイトペーパーを利用してC++26以降に漸次導入しようとしているようです。
P3613R0 On the beating of horses, and other matters
P3329R0の修正に反対する提案。
P3329R0では、std::filter_viewに対する破壊的な修正を行うことで、filter_viewをより安全かつ使いやすいものにすることを提案しています。
P3329R0については以前の記事を参照
この提案は、それに対して反対するものです。
P3329R0で報告されている問題は設計意図に沿わないようなものや意図しないバグではなくDRとして適切ではない、設計変更を支持する要素が弱い、破壊的変更の影響の見積もりが甘い、などを理由に挙げています。
提案では、P3329R0で提案されている修正がいかに間違っているかについて項目ごとに歴史的経緯や理由などを述べています。
P3614R0 Do not remove nor postpone access_context::unchecked
P3547R0の提案において、access_context::uncheckedを削除しないことを推奨する提案。
P3547R0では、クラス内エンティティに対するリフレクションを用いて何かをする際に、アクセスコンテキストを指定することでデフォルトでクラスのアクセス指定を無視したアクセスが可能であることを修正しようとしています。
P3547については以前の記事を参照
提案中では、従来のデフォルトであった無条件のアクセス許可を指定するためのコンテキストを表現するaccess_context::uncheckedというものがありました。SG7の初期投票では、これを含めることに対して懸念の声がありました。この提案はその結果に対して反論し、access_context::uncheckedを遅らせないことを推奨するものです。
リフレクション機能はC++をプラグラム可能なプラグラミング言語にするものであり、リフレクション機能だけで新しい言語機能を作成できるようにするもので、そのような新しい機能はクラスメンバにアクセスする必要がある場合、アクセス検眼や型の協力なしでアクセスできるべきであり、access_context::uncheckedがそれを可能にする、としています。access_context::uncheckedは十分に目立つため、コードの中に埋もれづらいともしています。
P3615R0 C++ Standard Library Ready Issues to be moved in Hagenberg, Feb. 2025
2月に行われたHagenberg会議でWDに適用されたライブラリに対するIssue報告の一覧
- 3578. Iterator SCARYness in the context of associative container merging
- 3956.
chrono::parseusesfrom_streamas a customization point - 4172.
unique_lockself-move-assignment is broken - 4175.
get_env()specified in terms ofas_const()but this doesn't work with rvalue senders - 4179. Wrong range in [alg.search]
- 4186.
regex_traits::transform_primarymistakenly detects typeid of a function - 4189.
cache_latest_viewshould be freestanding - 4191. P1467 changed the return type of
pow(complex<float>, int) - 4196. Complexity of
inplace_merge()is incorrect
P3616R0 Remove contracts on virtual functions for now
P2900のContractsから仮想関数に対する契約指定を削除する提案。
P2900R13で提案されている仕様では、オーバーライドされた仮想関数に対する契約の指定はオーバーライドする(基底の)関数に対する契約とは独立しており、その評価は呼び出し先/呼び出し側の契約注釈の観点から行われます。このため、基底クラスの契約と全く同じ契約を派生クラスでも指定したい場合は手動で行う必要があります。例えば、派生クラスのオーバーライド関数を派生クラスのポインタ/オブジェクトから直接呼び出す場合などにこのようなユースケースがあります。
しかし、基底クラスの仮想関数に対する契約注釈において基底クラスのプライベートメンバを使用していたりするとこれは不可能であり、現在の仕様はそのようなユースケースを満たすことができていません。
この問題は実装経験によって解決される事が想定されていますがそれには今しばらくの時間がかかるため、C++26に向けてのMVPとしてのContractsの機能からは仮想関数に対する契約指定を削除することを提案しています。
実装経験からは、契約注釈の自動継承・継承された契約注釈のオーバーライド・継承されたものをそのまま使用することを表明する方法・継承された契約注釈に関する診断機能、等についての経験が得られるとしていますが、P2900R13の現在の仕様はこれらのような妥当なユースケースをカバーするモデルへの進化の方向を閉ざすものになっています。
この提案はEWGのレビューと投票においてコンセンサスを得ており、P2900R14で仮想関数に対する契約指定が削除されています。
P3618R0 Allow attaching main to the global module
名前付きモジュールでmain()を定義する際の構文を変更する提案。
P3422R1では、名前付きモジュールにてmain()を宣言できるようにしたうえで、それを暗黙的にグローバルモジュールに属するようにすることを提案しています。
P3422R1については以前の記事を参照
この提案では、何の指定もないmain()を暗黙的にグローバルモジュールに属するようにするのではなく、明示的に言語リンケージ指定をしたものだけを許可するようににすることを提案しています。
| 現在 | この提案 |
|---|---|
module M; // Mに属する void f(); // グローバルモジュールに属する extern "C++" void g(); // グローバルモジュールに属する int main() {} // ill-formed extern "C++" int main() {} |
module M; // Mに属する void f(); // グローバルモジュールに属する extern "C++" void g(); // ill-formed int main() {} // グローバルモジュールに属する extern "C++" int main() {} |
この利点(というかP3422の欠点)としては次の事を挙げています
- P1203で提案されていたModuler
main()のような機能への道を閉ざす- ここではこれを提案しておらず、そのような機能候補を導入する余地を残しておく
- 名前付きモジュール内での通常の関数との一貫性向上
この提案は2025年2月の全体会議で採択され、C++26に導入されています。おそらく、C++20へのDRです。
P3619R0 Counter-examples for P2688R5
↓
P3619R1 Counter-examples for P2688R5
P2688R5のパターンマッチング機能が有用ではない例を挙げるスライド。
P2688については以前の記事を参照。
このスライドでは、P2688R5のmatch式によるパターンマッチングが既存の同等機能と比較して分かりやすくも使いやすくもならないような例を挙げています。説明文書がほとんどないので主張が分かりづらいですが、パターンマッチングによる書き方が説明なしだと良くわからず直観的とは言えないことを暗に主張しているものと思われます。
P3620R0 Concerns with the proposed addition of fibers to C++ 26
現在のfiber提案についての問題を指摘する文書。
fiber(軽量スレッド)を可能にするためのfiber_contextの提案がP0876で議論されています。fiber_contextは特定のスケジューラに依存せず、その部分を抽象化して扱うことで、その上にfiberを構成できるようにすることを目指すものです。
P0876については以前の記事を参照。
この提案は、fiber_contextが抽象化しようとしているスケジューラ(コンテキストスイッチ)に関する部分の実装が困難かつ多くの問題があるとして、P0876に反対するものです。
- コンテキストの定義
- ファイバーはユーザー空間におけるコンテキストスイッチを行うものであるが、コンテキストの定義が重要となる
- レジスタファイルの内容やスタックポインタは当然として、現在のシグナルマスク、保留中のシグナルや非同期コールバック、進行中の非同期I/Oなど、含めるべきものは多数あるがどこまでを含めるべきかの定義が困難であり、なされていない
- スレッドローカルストレージの使用
- 偶発的なデッドロック
- ファイバー対応スケジューラを持たないシステムでは、偶発的なデッドロックが発生する
- レイヤーの問題
fiber_contextは標準ライブラリという比較的高いレイヤに配置されようとしているが、その本質はスレッドと同等程度には低レベルに配置されるべき機能である- プラットフォームによって必ずしも提供されないこのような低レベルな機能を標準ライブラリとして持つことには前例がない
等を挙げています。総じて、fiber_contextの抽象化対象であるスケジューラとコンテキストスイッチ実装の困難さや標準ライブラリに適さない低レベルさを問題としています。
代替案や今後の方向性などを特に示しておらず、P0876の標準化に反対するもののようです。
P3623R0 Add noexcept to [iterator.range] (LWG 3537)
イテレータの範囲アクセス関数にnoexcept指定を追加する提案。
この提案は、P3010R5(valarrayとinitializer_listのbegin/end等の専用オーバーロードを削除する)のレビュー中に見つかった、std::data()の専用オーバーロードを削除した後汎用版にフォールバックすると、noexcept指定が変化する(noexceptありから無しになる)問題を解決するためのものです。
P3016R5については以前の記事を参照
例えばstd::initializer_listとstd::data()の場合、次のようにオーバーロードセットは次のようになっています
// 汎用オーバーロード(noexceptなし template<class C> constexpr auto data(C& c) -> decltype(c.data()); template<class C> constexpr auto data(const C& c) -> decltype(c.data()); // std::array用オーバーロード template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept; // initializer_list用オーバーロード(P3016で削除しようとしている template<class E> constexpr const E* data(initializer_list<E> il) noexcept;
このように、専用オーバーロードにはnoexceptが指定されているものの、汎用オーバーロードは基本noexceptが指定されていません。これによって、std::initializer_listの専用オーバーロードを削除するとnoexcept演算子によってそれが可視になります。
// P3016前後で結果が異なる bool f(std::initializer_list<int> il) { return noexcept(std::data(il)); }
この提案はこの問題に対処するために、initializer_listのstd::data()オーバーロードを<iterator>に移してnoexceptを維持するとともに、汎用のstd::dataに対しても条件付きnoexcept(noexcept(noexcept(c.data())))を付加するようにするものです。
そして、P3016R5の目的がコンテナとの一貫性の向上のためだったこともあり、そのほかの範囲アクセス関数に対してもそれぞれnoexceptを付加するようにすることを提案しています。ただし一様ではなく、それぞれ次のような変更が提案されています
begin()/end(): 汎用オーバーロードに条件付きnoexceptを追加rbegin()/rend(): 汎用オーバーロードに条件付きnoexceptを追加、配列オーバーロードにnoexceptを追加あcrbegin()/crend(): 汎用オーバーロードに条件付きnoexceptを追加size(): 汎用オーバーロードに条件付きnoexceptを追加data(), empty(): : 汎用オーバーロードに条件付きnoexceptを追加
std::cbegin()/cend()に関しては既に条件付きnoexcept指定されていましたがその他のものは特にされていなかったため、それを付加しています。
この提案の内容はすでにMSVC STLにおいて実装されており、一部はlibstdc++でも利用可能になっています。
P3625R0 either neither
どれか、どれでもない、を簡単に表現可能なコンセプトの提案。
この提案は、型のリストとの単純なマッチングを行うための2つのコンセプト、either<T, Ts...>とneither<T, Ts...>を提案しています。
namespace std { template<class T, class... U> concept either = (same_as<T, U> || ...); template<class T, class... U> concept neither = !either<T, U...>; }
either<T, Ts...>はTs...の中にTと同じ型がある場合に満たされ、neither<T, Ts...>はTs...の中にTと同じ型が無い場合に満たされます。
筆者の方の経験において、複数のプロジェクトでこのようなコンセプトの必要性に遭遇したことや、cppreferenceのsame_asのページやstackoverflowにおける質問などから、このようなコンセプトの必要性を提案しています。
| 現在 | この提案 |
|---|---|
template<typename T> requires(same_as<T, char> or same_as<T, short>) void func(T) { … } |
template<either<char, short> T> void func(T) { … } // or just: void func(either<char, short> auto) { … } |
| 現在 | この提案 |
|---|---|
template<typename T> requires(not same_as<T, short> and not same_as<T, int>) void func(T) { … } |
template<neither<short, int> T> void func(T) { … } // or just: void func(neither<short, int> auto) { … } |
P3626R0 Make predicate exceptions propagate by default
契約注釈の評価時に、その条件式から送出された例外を契約機構がハンドルしないのをデフォルトにする提案。
P2900R14で提案中のContracts機能においては、契約条件式を評価した際に例外が送出されるとそれも契約違反の一部として扱って、observe/enforceセマンティクスでは違反ハンドラが呼ばれます。例外処理のためのオーバーヘッドが増えることなどからこの動作については異論があり、通常のハンドルされない例外と同様にスタックを伝播させるべきという意見があるようです。
この提案は、その方向性のための文言を提供するものです。
そのため、厳密にいえばこの提案はそのことを提案しているわけではありません(が、他に明示的にそれを提案している提案もないはずです)。
P3627R0 Easy-to-adopt security profiles for preventing RCE (remote code execution) in existing C++ code
リモートコード実行を防止するためのセキュリティプロファイルのアイデアスライド。
ここでは、既存のプラクティスを活用しかつ既存C++コードに大きな変更を加えることなくリモートコード実行を防止するための、セキュアプロファイルを導入するアイデアが紹介されています。ここでのプロファイルとは、目下議論中のプロファイル機能の具体的なプロファイルの一つとしてのものです。
これは何かの提案の紹介というわけではないですが、提案というわけでもなさそうです。
P3628R0 break label; and continue label;, tl; dr
P3568R1の短縮バージョンの文書。
P3568については以前の記事を参照(R1は上の方
この文書は、提案のモチベーションや設計、文言をP3568から簡潔にまとめたものです。とはいえこちらを提案として運用していくわけではなさそうで、EWG等のメンバに向けて読みやすくしたものの様です。
P3630R0 Slides for P3568R0
P3568の説明スライド。
P3568についてはすぐ上などを参照してください。
ここでは主に、構文の選択(CのN3355とN3377)についてが簡潔に紹介されています。
P3632R0 P3564R0: Make the concurrent forward progress guarantee usable in bulk
↓
P3632R1 P3564R0: Make the concurrent forward progress guarantee usable in bulk
P3564R0の説明スライド。
P3564R0については以前の記事を参照
このスライドでは、P3564R0のモチベーションや理由、やろうとしていることが簡潔にまとめられています。
P3633R0 A Byte is a Byte
C++標準として1バイトを8ビットとして規定することに反対する提案。
この提案は、1バイトを8ビットとして規定しようとしているP3477に反対するものです。
P3477については以前の記事を参照
提案では次のようなことが述べられています
- 一部のDSPでは1バイト=16ビットや24ビットが珍しくなく、そのような環境でもC++11がサポートされている
- 組み込み開発の現場からのフィードバックに時間がかかる
- C++の標準化委員会には組み込み開発者の声が届きづらい現状がある
- C++の標準化プロセスは長く複雑で、通常の提案でさえもフィードバックを得るのに時間がかかる
- 組み込み開発ではその特性上ISOの標準化プロセスと同じくらいの厳格さがあり、言語のアップデートには時間がかかる
- 組み込み製品は必ずしも後からアップデートできないことや、すでに動いているデバイスにアップデートを適用しても壊さないようにするために、慎重な検討が行われる
- このため、組み込み分野では特に、C++におけるアップデートの効果が検証・確認されフィードバックされるまでにかなり時間がかかる
- 組み込みベンダが標準仕様への追随に消極的なわけではない
- 組み込みプラットフォームが最新のC++をサポートしないからサポートする必要がないという意見は、自己成就的な予言であり、その変更によってそれが達成される
- C++を過剰に標準化すべきではない
- その変更は誰のためのものか
- P3477ではモチベーションの一つとして、ほとんどのプログラマにとっては何も変更されないと主張しているが、何も変更されないなら修正の必要はない
- 利便性を無視した標準化は背後にあるハードウェアの現実を無視している
- 提案された修正の利点が何で、誰のためのものなのかが不明
P3477の採択はC++標準が組み込み業界を切り捨てる判断をするのと同義であり、C++が多様なハードウェアで利用され続けることを拒否するものとなる、ということに強く警鐘を鳴らしています。
P3635R0 We shouldn't rush to require either CHAR_BIT==8 or (u)intNN_t
C++標準として1バイトを8ビットとして規定することに反対する提案。
この提案も一つ前のP3633と同様に、1バイトを8ビットとして規定しようとしているP3477に反対するものです。
こちらでの反対理由はP3633とは少し異なった方向からのもので
- 動機づけが弱い
- 議論をするたびに新しい情報が明らかになる
- にもかかわらず、提出されたタイミングが新規提案をC++26へ進める事の出来る最後のタイミング
CHAR_BIT==8を規定しても、(u)intNN_t型が必須の型として定義できるようになるわけではないCHAR_BIT==8だとしても、他の2のべき乗サイズの型が存在するとは限らない
(u)intNN_t型が拡張整数型として定義されているプラットフォームが存在する- つまり、標準の
int等の基本型のエイリアスではないため、基本型との互換性が基本的にない - P3477によって
(u)intNN_t型が必須型となるとすると、標準ライブラリに拡張整数型のサポートが必要になる- そのような考慮は現在全く行われていないため、多くの検討作業が必要
- ライブラリ側に変更が及ばないという前提が崩れている
- つまり、標準の
- ネットワークライブラリのために必須というわけでもない
- 単に、ネットワークライブラリが
CHAR_BIT==8の環境でのみ有効である、ように規定すればいい
- 単に、ネットワークライブラリが
そのほか、P3477の動機について一つ一つ反対意見をあげており、C++26ではリジェクトすべきとしています(時間の無駄とまで述べています)。
P3636R0 LEWG Hagenberg presentation for P3581 No, inplace_vector shouldn't have an Allocator
P3581の紹介スライド。
P3581については以前の記事を参照
このスライドでは、inplace_vectorをアロケータ対応させる議論の変遷をまとめています。特に、関連提案がいつの全体会議でどのように進行していったのかについて記載しています。
P3637R0 Inherit std::meta::exception from std::exception
std::meta::exceptionをstd::exceptionから派生させるようにする提案。
P3560では静的リフレクションにおけるエラー報告とハンドリングの方法として例外を使用することを提案しています。そこでは、専用の例外型としてstd::meta::exceptionを使用することを提案しているものの、これはstd::exceptionから派生するものではありません。
この提案はこの設計選択に反対し、std::meta::exceptionもstd::exceptionの派生クラスであるべきとするものです。
P3560でそのような選択がなされたのはどうやら、LWG Issue 4087で報告された古い情報に基づく.what()のエンコーディングの制約に関する懸念によるものだったようで、現在それは解消されています。したがってstd::exceptionからの派生を避ける理由はもはやないとのことです。
一貫性以外の理由としても、コンパイル時に送出される例外はstd::exceptionの派生型のものもあり得るため、コンパイル時のテストを行うような場合に少なくとも2つの例外をキャッチするコードを書かなければならなくなります。std::meta::exceptionがstd::exceptionから派生することで1種類のみを考慮すればよくなります。
ただし、提案ではstd::meta::exceptionのコンストラクタに渡されるエラー文字列(UTF-8)の内容がcharのエンコーディングで表現可能な場合にのみ、UTF-8から変換した文字列を返し、そうでないならばコンパイルエラー(定数式で実行できない)にすることを提案しています。
この提案はLEWGのレビューで承認され、P3560へ適用されています。
- P3560R0 Error Handling in Reflection - WG21月次提案文書を眺める(2025年01月)
- LWG Issue 4087. Standard exception messages have unspecified encoding
- P3637 進行状況
P3638R0 Core Language Working Group "ready" Issues for the February, 2025 meeting
2025年01月に行われたHagenberg会議でWDに適用されたコア言語に対するIssue報告の一覧。
- 2549. Implicitly moving the operand of a throw-expression in unevaluated contexts
- 2703. Three-way comparison requiring strong ordering for floating-point types, take 2
- 2943. Discarding a void return value
- 2970. Races with volatile sig_atomic_t bit-fields
- 2990. Exporting redeclarations of namespaces
P3639R0 The _BitInt Debate
C23の_BitIntをC++ではライブラリ型として導入すべきとする提案。
_BitIntはC23で導入された、任意のNビット(正確にNビット)幅の整数型を得るための機能です。
// 8ビット符号なし整数型を255で初期化 unsigned _BitInt(8) x = 0xFFwb; // wbリテラルはこのケースでは必要ない
見た目はマクロっぽいですがどうやらマクロではないようで、この_BitIntは簡単に次のような性質があります
int型への昇格は行われない- 混合符号比較や暗黙変換、その他整数に関する柔軟性を高める機能がサポートされる
- 標準整数よりも変換ランクが低いため、標準整数との間の演算では標準整数型に暗黙変換される
_BitInt(8) op int->int_BitInt(32) op int->intint型の幅が32ビットの場合
- ただし、
_BitInt<N>のNが他方の標準整数型のビット幅よりも大きい場合は変換ランクが高くなる
このように、_BitIntは標準整数を補完するものであり、より安全な振る舞いをする整数型で置き換えるための機能ではありません。
CとC++は多くの部分で相互運用が可能なコードを記述することができるため、Cでサポートされる機能はC++でもサポートすることが可能であり_BitIntもC++でもサポートしてほしいという需要が生じるのは自然なことです(この提案のモチベーションがまさにそこにあります)。その場合はC++でもCと同様に標準整数型を補完するものとして導入し、Cの_BitIntとABI互換があるべきです。しかしそこには、_BitInt(あるいは同等の型)を基本型として導入するか、ライブラリ型として導入するか、選択肢があります。
この提案はこれらの利点や欠点について検討し、この方向性についての合意を促すことを目的とするものです。
基本型として導入する場合のC++での実装例
template <size_t N> using bit_int_t = _BitInt(N); template <size_t N> using bit_uint_t = unsigned _BitInt(N)
ライブラリ型として導入する場合の実装例
template <size_t N> class bit_int { private: _BitInt(N) _M_value; public: // constructors, operator overloads, ... }; // bit_uintも同様にunsigned _BitIntをラップする形で実装する
どちらを選択するにせよ、このような前例はcomplexや_Atomic、_Float128などがあります(_BitIntを直接利用することはこれらと一貫していません)。
そのうえで、提案では両者の利点を比較しています
基本型の利点
- Cの機能との完全な互換性
- Cでは
_BitIntをswitch文やビットフィールドで使用できるが、C++のライブラリ型では不可能 - ❌ 反論: クラス型であっても条件付きサポートの例外を設けることは可能な可能性がある
- しかし、これは
bit_intが_BitIntのラッパーである場合にのみ可能であり、純粋にライブラリで実装されている場合は不可能
- しかし、これは
- Cでは
unsigned _BitInt- もし
class bit_intがあり、Cとの相互運用性のために_BitInt互換マクロが存在する場合、unsigned _BitIntはunsigned bit_intに展開されるため機能しない - なおこの問題は、
_Atomicや_Float128、complexでは発生せず、_BitIntに固有の問題
- もし
_BitIntとclass bit_intはうまく共存できないbit_intがクラステンプレートの場合、一般的な実装は_BitIntをそのテンプレートでラップすることであり、その場合一部の実装ではclass bit_intと_BitIntの両方が存在するが、インクルード順序によって問題を引き起こす可能性がある- ❌ 反論:
<stdint.h>が互換マクロを定義していれば、ユーザーはapi.hにそのヘッダーを含めることでこの問題を解決できる
_BitIntはC++に関係なくCでは必須の機能である_BitIntはコンパイルが速い- 純粋なライブラリ実装は一時的な解決策に過ぎない
_BitIntはオーバーロード解決の柔軟性を提供する_BitIntは特別な推論能力を持つ可能性があるfoo(0);のように、標準整数を渡したときにbit_int_t<N>の特殊な推論ルールが許可される可能性がある。これはクラステンプレートでは不可能- ❌ 反論: この問題はより一般的であり、通常の回避策はCTAD(Class Template Argument Deduction)に依存すること
- 特別な推論ルールを設けるよりも、一般的に解決することが望ましい
ライブラリ型の利点
_BitIntは移植性がないが、class bit_intは移植性がある_BitIntは多くの不適切なCの整数機能を継承するclass bit_intの方が実装が容易- Boost.Multiprecisionなど、すでに多くのC++用多倍長整数実装が存在し、それらを標準ライブラリに統合できる。基本型として標準化すると、ABIを確定させる必要があり、その影響は大きい
- ❌ 反論: 実装の労力は特にそれが高品質/高性能でなければならない場合、いずれにしても必要になる
- ライブラリ実装であっても、intrinsicsやインラインアセンブリの形でアーキテクチャの知識を利用する必要がある
- 移植性のある
class bit_intがより早く手に入る可能性が高い- MSVCがC23の
_BitIntをいつ実装するかは不明 - 基本型を要求するとこの機能がずっと遅れるか、あるいは手に入らない可能性がある
- ❌ 反論: すべてのコンパイラが広い幅の
_BitInt(N)をサポートするようになれば、この点はそれほど重要ではなくなる
- MSVCがC23の
class bit_intは教えやすいclass bit_intは文言への影響が少なく、落とし穴も少ない- 言語に新しいクラス型を導入するだけなら、コアの文言に全く影響を与えず、文言のバグや微妙なABI破壊を引き起こすことはない
- 例えば、
iota_viewのdifference_typeの定義など、基本型を追加することには大きな文言への影響が伴う
- 例えば、
- ❌ 反論: これは本末転倒なもの。委員会時間という貴重なリソースは存在するが、文言への影響が設計を決定すべきではない
- 言語に新しいクラス型を導入するだけなら、コアの文言に全く影響を与えず、文言のバグや微妙なABI破壊を引き起こすことはない
この提案の結論としては、好みは無いとしながらもライブラリ型として導入することを推奨しています。
SG22/EWGのレビューと投票では、一貫して基本型とすべきというコンセンサスがありました。そのため、その方向で議論されていくと思われます(P3666で提案していくようです)。
P3640R0 Make contracts reliable by default
契約注釈のデフォルトセマンティクスをenforceにしておく提案。
この提案では、observe/ignoreセマンティクスの場合の契約注釈が実際には危険であると指摘しています。例えば次のようなコードでは
int ddref(int** p) pre(p) pre(*p) { return **p; }
事前条件が破られない場合関数本体内および事後条件において未定義動作が発生します。enforce/quick_enforceセマンティクスではプログラム終了などによって起こらないようにすることができますが、observe/ignoreセマンティクスでは契約違反後も継続されるため回避できません。
このようなContracts機能の危険性を回避するために、契約注釈のデフォルトセマンティクスをenforceにしておくことを提案しています。
またさらに、ラベル指定がC++26に間に合わずそれが来ても上記のような問題の回避に信頼できないとして、enforce系以外のセマンティクスを選択するには追加のアノテーションを必須とすることも提案しています。
なお、この提案はSG21のレビューで否決されています。そもそも、上記の主張がContractsおよび契約プログラミングを正しく理解していないもので、提案の前提が間違っているためだと思われます。
P3641R0 Rename std::observable to std::observable_checkpoint, and add a feature-test macro
std::observableをstd::observable_checkpointにリネームする提案。
std::observableはP1494R5で導入された、観測可能なチェックポイントを明示的に作り出すための関数です。P1494については以前の記事を参照
この関数名については、意図をうまく表現できていない(何がobservableなのかよくわからない)、observerパターンと関連があるように見える(実際はない)、短くかつ汎用的な名前であるため将来の別の機能で使えなくなる、等の問題点が指摘されているようです。
この提案は、それを受けて名前を変更することと、機能テストマクロの追加(おそらく忘れられていた)を提案するものです。
この提案はEWG/LWGのレビューを大きな反対なく通過し、2025年6月の全体会議でC++26へ採択されたようです。
P3642R0 Carry-less product: std::clmul
整数のキャリーレス乗算を行う関数の提案。
キャリーレス乗算は、二進数値の乗算において各桁の桁上がりを考慮しない乗算です。
2つのビット列a, bに対するキャリーレス乗算cは次のように定義されます
$$ c_i = \bigoplus{j=0}^i a_j \And b{i-j} $$
ここで、\bigoplusはXORによる総和を表し、下付きのi, jは0始まりのビットインデックス(右->左)の指定を表し、$\And$はビット積(ビット値とbool値を同一視した時の論理積)を表します。
別の説明をすると、乗算を筆算で書いた時に、各桁の積を求めた後に各桁毎に足していく際に加算の代わりにXORによって各桁の値を求めることに相当します。例えば、10100010と10010110の2つの二進数値のキャリーレス乗算は次のようになります
10100010
10010110
--------
00000000
10100010|
10100010|| ↓への可算はXORで行う
00000000|||
10100010||||
00000000|||||
00000000||||||
10100010|||||||
---------------
101100011101100
キャリーレス乗算はまた、XOR multiplication や polynomial multiplication(各ビットが係数であるガロア体GF(2)における2つの多項式の乗算に等しいため)とも呼ばれるようです。
このキャリーレス乗算はCRC、暗号計算、ビット演算などにおいてよく使用されており、CPUの命令によるHWサポートがあります。そのため、<bit>の各関数と同様に標準で提供するようにしておく提案です。
ここで提案しているのはキャリーレス乗算を単純に行うstd::clmul()と、オーバーフロー検知機能付きのstd::clmul_wide()の2つです。
namespace std { template<unsigned_integral T> // constraint is exposition-only constexpr T clmul(T x, T y) noexcept; template<class T> struct mul_wide_result { T low_bits; T high_bits; }; template<unsigned_integral T> constexpr mul_wide_result<T> clmul_wide(T x, T y) noexcept; }
clmul_wide()はP3161R2で提案されているmul_wide()に倣ったオーバーフロー検知版の関数で、キャリーレス乗算を無限精度で行った後に結果の値の上位と下位のNビット(NはTのビット数)をhigh_bits, low_bitsにそれぞれ返すものです。
提案文書より、2次元のヒルベルト曲線を計算する例
pos hilbert_to_xy(uint32_t i) { // De-interleave the bits of i. uint32_t i0 = std::bit_compress(i, 0x55555555u); // abcdefgh -> bdfh uint32_t i1 = std::bit_compress(i, 0xaaaaaaaau); // abcdefgh -> aceg // Undo the permutation that Hilbert curves apply on top of Z-order curves. uint32_t A = i0 & i1; uint32_t B = i0 ^ i1 ^ 0xffffu; uint32_t C = std::clmul(A, -1u) >> 16; // 👈 uint32_t D = std::clmul(B, -1u) >> 16; // 👈 uint32_t a = C ^ (i0 & D); return { .x = a ^ i1, .y = a ^ i0 ^ i1 }; }
ヒルベルト曲線では、配列の1次元インデックスを特定の2x2行列内の2次元インデックスにマッピングしますが、その際に隣接する2つの要素の間のインデックス距離が0になるようなマッピングを行うものです。例えば、i = 0, 1, 2 ... 0xe, 0xfに対しては次のようなマッピングを返します
0 1 e f 3 2 d c 4 7 8 b 5 6 9 a
- Carry-less product - Wikipedia
- P3161R2 Unified integer overflow arithmetic - WG21月次提案文書を眺める(2024年07月)
- P3639 進行状況
P3643R0 std::to_signed and std::to_unsigned
整数型を対応する符号付/符号なしの整数型に簡易に変換する関数の提案。
整数数値の処理やビット操作等では、入力整数値をまず対応する符号付/符号なしの型に変換してから処理する事が良くあります。現在、それを最も簡易に実行できるのは関数スタイルキャストです。
template<class T> T arithmetic_shift_right(T x, int s) { return T(std::make_signed_t<T>(x) >> s); } template<class T> T wrapping_add(T x, T y) { constexpr unsigned to_int_promotion_defense = 0; return T(to_int_promotion_defense + std::make_unsigned_t<T>(x) + std::make_unsigned_t<T>(y)); }
これは冗長性が高くバグらせやすかったり(xの型がTであることを要求していない)、関数スタイルキャストはほぼCのキャストであるためプロジェクトによってはスタイルで禁止されている場合があります。
上記の場合にはstaic_cast<std::make_signed_t<T>>(x)のように書くのが正しいですが、これはコードを複雑化します。あるいは、std::make_signed_t<decltype(x)>(x)のように書くのも適切ですが、これもあまり改善にはなっていません。
この提案は、この手の変換を簡単に書くための関数を用意することでこのような問題の解決を図るものです。
// 宣言と実装の例 namespace std { template<class T> constexpr std::make_signed_t<T> to_signed(T x) noexcept { return static_cast<std::make_signed_t<T>>(x); } template<class T> constexpr std::make_unsigned_t<T> to_unsigned(T x) noexcept { return static_cast<std::make_unsigned_t<T>>(x); } }
GIthubのコードの検索では、同名の関数またはmake_signed/make_unsignedへのstatic_castのようなコードの使用例がおよそ1万3千件のC++ファイルで見つかったとのことです。関数の命名はそれらの既存の使用例を根拠にしています。
P3650R0 21st Century C++
ビャーネ・ストラウストラップによって書かれた、現在のC++によるプログラミングを紹介する文書。
この文書では、C++の基礎知識を持ちながら古いスタイルのプログラミングから脱却できないような開発者を対象に、現在のC++プログラミングにおける重要な概念について説明しています。ここで説明されているのは次の項目です
- リソース管理
- ライフタイム管理
- エラー処理
- モジュール
- ジェネリックプログラミング
そして、これらに加えてガイドラインとプロファイルについての紹介もしています。
P3651R0 Note to the C++ standards committee members
C++26でプロファイル機能を緊急的に採用すべきとする提言。
この文書は、プロファイル機能の議論の中でやり取りされた内部の文書だったようですが、WG21メンバのだれかがその一部を外部に公開したことで無駄な論争を招いていたようで、それを受けて公開するに至ったものです。
これはおそらくP3611R0(上の方)の提案の議論の流れの中にあるもので、外部環境の安全性への圧力が強まっている中で何も行動しなければC++が新規に使用されなくなり、それによってC++への投資が行われなくなりC++言語やコミュニティが衰退するという危険性を説いています。P3611はそれへの対応としてC++26で標準ライブラリの堅牢化とプロファイル機能の採択を行うことを提案するものですが、この文書も別の角度からそのことを支持し説明しています。
C++26では結局、標準ライブラリの堅牢化だけが採択され、プロファイル機能はホワイトペーパーとして作業を続けていくことになっています。
P3652R0 Constexpr floating-point functions
std::to_chars/std::from_charsの浮動小数点数版オーバーロードをconstexpr指定する提案。
どちらの関数も、P2291R3にて整数型のオーバーロードについてはconstexpr指定されています。その際、P2291R3の検討時点ではstd::to_chars/std::from_charsの実装経験が乏しく、浮動小数点数の変換についてを定数式で実行可能かどうか不透明な部分がありました。
しかし現在では主要な3実装で実装が出そろい、使用されているアルゴリズムも定数式で実行可能であることが判明しているようです。そのため、この提案では残った浮動小数点数オーバーロードについてもconstexpr指定しようとしています。
#embedやコンパイル時のメッセージ出力に関する改善提案によって、定数式で文字列と数値を相互変換できることの重要性がP2291の時よりもさらに高まっている、というのがモチベーションとして挙げられいます。
筆者の方はfast_floatとdragonboxというアルゴリズム実装のライブラリの擁するto_chars/from_charsについてconstexpr対応の作業を行い、C++20以降の機能を使用することで簡単にできたとしています。
P3654R0 Slides for P3516
P3516の紹介スライド。
P3516については以前の記事を参照
このスライドはLEWGのメンバに向けてP3516の提案を紹介し、ユースケースの紹介ややFAQの説明等をしています。
P3655R0 zstring_view
null終端文字列専用のstd::string_viewの提案。
std::string_viewは文字列を引数に取る場合に汎用的に使用可能な型ですが、参照する文字列はnull終端されない可能性があることによって使いづらい場合があります。特に、null終端文字列を案に要求するC APIのラッパコードなどにおいては、std::string_viewを引数に取ることでむしろその情報が欠落するという欠点があります。そのため、そのような場所では引き続きstd::string_viewが解決したはずの問題(文字列引数型には何を使用すべきか?)が残されており、std::string_viewが追加されることでより複雑化しています。
現在、そのような場所でstd::string_viewが使用される場合はnull終端を仮定するかコピーして終端を追加するかが選択され、あるいはnull終端保証のあるstd::string_view(zstring_viewやcstring_view)を作成して使用されています。
const char*が引き続き使用される場合、長さ情報が失われることから内部で文字列長計算(strlen())が行われてしまい、これは二度手間となります。
この提案はnull終端文字列を取る場合の引数型の決定版として使用可能なstd::string_viewであるstd::zstring_viewを標準ライブラリで用意しておくようにするものです。
この提案のstd::zstring_viewはstd::string_viewとは明確に異なる型(継承関係もない)として定義されます。しかし、一部異なる部分があります
- コンストラクタはデフォルト/コピーコンストラクタを除くと、
const char*を取るものとそれに加えて長さを取るものの2種類のみ substr()は1引数のものと2引数のものに分割- 1引数のものは末尾を維持するもので、
std::zstring_viewを返す - 2引数のものは
std::string_viewを返す
- 1引数のものは末尾を維持するもので、
remove_suffix()はdeleteされるc_str()が利用可能- 文字型が同じ
string_viewへの暗黙変換が可能
このzstring_viewはnull終端というプロパティを型で表現することが主な役割で、null終端文字列を保証する積極的な検査などは行っていません(コンストラクタの事前条件チェックは意図していると思われますが)。
この提案では、標準ライブラリ内でnull終端文字列を受け取るインターフェースをzstring_viewで置き換えることまでは提案していません。
P3656R0 Initial draft proposal for core language UB white paper: Process and major work items
コア言語のUBに対策するための言語機能に関するホワイトペーパーのための作業や手順についての提案。
安全性への要求の高まりを受けて、コア言語のUBに対して何らかの対策を行う機能についての議論が活発になっており、現時点でもEB・プロファイル・暗黙の契約などの方法が並行して提案されています。
このような機能の議論は、それぞれを個別に進めて結果的に似た機能が並立する事態を防止するために、ある程度包括的な議論と検討が必要ですが、同時に緊急性が高いものであるためより高い頻度でリリースしてフィードバックや実装経験を積んでそれをもって標準になるべく早く導入することが求められています。そのため、通常の3年ごとのリリースサイクルとは別のサイクルが必要になります。
WG21ではそのためにTSではなくホワイトペーパーというISOの持つ仕組みを活用することにしたようで、この文書はその初期ドラフトとして作業をどのように行っていくか、直近どのような作業が必要か、についてまとめたものです。
作業手順は次のようなものが提案されています
- 空のホワイトペーパーから始める
- ホワイトペーパーのワーキングドラフトに採用する各項目についてEWGの承認を得る
- ホワイトペーパーのワーキングドラフト全体についてEWGの承認を得てCWGに転送し、文言の修正を行う
- 全体会議で承認を得てSC22にホワイトペーパーを転送し、公開投票を行う
作業は専用のGithubリポジトリで行い、PRやIssueを活用することを提案しています。
現時点で挙げられているワークアイテムは次の
- 言語UBの列挙
- 目標: コア言語にあるUBの完全なリストを得る
- 対策のためのツール(昨日候補)の列挙
- 目標: 特定のUBに対して対処可能なオプションについての合意を得る
- この時点では一つを選び出すことを意図していない
- 現時点の候補
- Erroneous Behavior
- プロファイル(P3589R2など
- 契約
- 暗黙の契約ではない契約機能
- ラベル指定を必須とする
- その他候補
- UBのWell-defined化(動作を定義する
- 全てのUBをEBにする
- 特定のUBのみEBにする
- UBで言語組み込みの契約チェック(暗黙の契約)を有効化する
- 目標: 特定のUBに対して対処可能なオプションについての合意を得る
- UB毎に、どのようなツールを使用できるかを検討する
- まとめて対処可能なUBのグループを作成する
- 同じ方法を適用することができるような、まとめて対処することのできるUBのグループを特定する
- 特定のUBが複数のグループに所属することを許可する
この提案そのものもEWGの承認を得て進めていこうとしています。
P3657R0 A Grammar for Whitespace Characters
C++規格文書における空白(whitespace)の扱いを明確化する提案。
以前のP2348という提案では、コメントも含めた空白文字の扱いについて見直そうとしていますが作業負荷が大きくC++26には間に合わないことが想定されています。この提案は、P2348の内容の一部だけを先にC++26に導入しようとするものです。
P2348については以前の記事を参照
現在のC++の規格では特に翻訳フェーズ4までの間に空白(whitespace)や空白文字(whitespace character)という言葉が多用されていますが、実はその定義がきちんとなされていません。空白にはどのような文字が含まれるのかが明確ではなく、改行文字を除くというように追記されて使用されている場所も多くあります。
この提案では、空白・空白文字の厳密な定義を行い、それとして扱われるものと扱われないものを明確化しようとしています。具体的には次のような変更を提案しています
- whitespace-charactersという用語の導入
whitespace-characterという文法規則の導入- 次のいずれか
- U+0009 CHARACTER TABULATION
- U+000B LINE TABULATION
- U+000C FORM FEED
- U+0020 SPACE
- 次のいずれか
- 改行(new-line characters)はwhitespaceではるものの
whitespace-characterには含まれない - 関連する文字についてユニコードのコードポイントと文字名による明確な指定を行う
- 空白文字の意味でspaceを使用しているところや、horizontal/vertical tab、form feed等
この提案の変更は編集上のものであり、動作に何かしらの変更を加える事を意図したものではありません。また、この提案が先に採用されたとしてもP2348が不要になるわけではなく、P2348のベースとなることを意図しています。
P3658R0 Adjust identifier following new Unicode recommendations
識別子に使用可能な文字の範囲を広げる提案。
C++23のスコープ内では、P1949の採択に伴ってユニコードのUAX31に従う形で識別子(identifier)に使用可能な文字が制限されました(これは以前のバージョンへのDRとなっています)。しかし、P1949の採択後にUAX31が更新され、「Unicode Technical Standard #55, Unicode Source Code Handling(UTS #55)」というものが新たに公開されました。ここで一部の数学記号が新たに識別子の文字として使用可能なように取り入れられたため、C++もこれに倣うようにしようとするものです。
この提案による変化の例
| 識別子例 | C++11~C++20 | P1949後 | この提案 |
|---|---|---|---|
Hawaiʻi, ǃnu, 𒉭, 𓋴𓅱𓎛𓏏𓆇, íkǃaːⁿd̥ǎ̤, fʹ, grad_𝑓, 𝑥2, xⁿ, 𝔰𝔬 |
OK | OK | OK |
𝛁f, x², x₂, 𝜕Ω |
OK | NG | OK |
∇f, ∂Ω, C∞ |
NG | NG | OK |
🜅, , 🙵🞴🙶🙷 |
OK | NG | NG |
どうやら、数学的な定義などに対応するコードを記述する場合にユニコードの数学記号を変数名等に使用していたコードが存在していたらしく、最初のUAX31ではこの考慮が漏れていたようです。P1949の議論と並行でこの検討は進められ、P1949採択後にUAX31が更新されたためC++には反映できていませんでした。
これはP1949実装後のClangでバグレポートとして報告されており、Clangでは既に修正済みです。そのため、この提案は以前のバージョンに対する(おそらくC++11以降)DRとすることを提案しています。
ただしこの提案でも、絵文字が再び使用可能になるわけではありません。
- P1949R7 C++ Identifier Syntax using Unicode Standard Annex 31 - WG21月次提案文書を眺める(2021年04月)
- Clang 14 rejects certain Unicode characters in identifiers that are accepted by Clang 13 and the C++ Standard · Issue #54732 · llvm/llvm-project
- P3658 進行状況
P3660R0 Improve reference_wrapper Ergonomics
std::reference_wrapperのインターフェースを改善する提案。
std::reference_wrapperは参照オブジェクトとして、nullにならない+再代入可能という性質をもちます。このオブジェクト的に扱える参照型というのは様々なところで便利であり、そのような参照型が欲しい所では非常に良く使用される一般的なパターンとなっています。例えば参照をメンバで保持したい時や、参照をコンテナに入れたいときなどに良く使用されています。
しかし、これは歴史的にはテンプレートメタプログラミングの文脈で参照を扱いやすくするためのユーティリティとして設計された経緯があるため、次のように微妙に使いづらいところがあります
- 名前が長い
- メンバアクセスに
.get()が必要
この提案は、std::reference_wrapperを改良して使いやすくしようとするものです。次の改善をしようとしています
std::reference<T>としてstd::reference_wrapper<T>のエイリアステンプレートを追加- メンバアクセスのために
->演算子を追加- 対称性のために
*演算子も追加
- 対称性のために
std::referenceとstd::reference_wrapperを<utility>から使用できるようにする
小さな変更ではありますが、これによって確実に使いやすくなります。
P3661R0 Attributes, annotations, labels
アノテーションに適した属性の提案。
C++における属性はその無視可能性についての懸念から、アノテーションやラベルのようなものや小さな機能追加には適していないことが分かってきています。しかし一方で、種々のアノテーションの必要性についてはは度々議論に浮上しており、それが必要なことは明白です。
この提案では、既存の属性とは別のものとして、アノテーションやラベル指定に使用可能な属性構文を導入しようとしています。
このような属性は次の提案において必要となる可能性があります
- P3394R1: リフレクション用のアノテーション
- P3589R0: プロファイル構文
- P3400R0: 契約注釈のラベル指定
ここではまだ具体的な構文について言及されてはいませんが、いずれの場合でも重要な性質として無視することができないものであることを挙げています。そして、可能なら構文を共通化することを提案しています。
P3662R0 Improve Increment and Decrement Operator Syntax
インクリメント/デクリメント演算子オーバーロードの構文を改善する提案。
インクリメント/デクリメント演算子はクラスにおいて次のように書くことでオーバーロードすることができます。
struct S { auto operator++() { ... } // ++s auto operator++(int) { ... } // s++ auto operator--() { ... } // --s auto operator--(int) { ... } // s-- };
しかし、これらの構文はどちらが前置でどちらが後置かが分かりづらく、区別するためのint引数も直感的ではありません。
これは歴史的に、まず初めに前置と後置を区別しないインクリメント演算子のオーバーロードがあり、そこから2つを区別するための構文を追加しようとしたときに新しいキーワードの導入を避けて変更を最小限(特に破壊的変更なしで)にするために今の構文になっています。
現在のC++環境で同じことが行われた場合、文脈依存キーワードを用いるなどしておそらくもう少し良い構文を採用することができるでしょう。この提案はその発想の下、これらの演算子オーバーロードの構文を改善しようとするものです。
この提案では、新しいインクリメント/デクリメント演算子オーバーロードの構文として、次のような構文を提案しています。
struct S { auto operator++ prefix() { ... } // ++s auto operator++ postfix() { ... } // s++ };
この構文は、prefix/postfixというキーワードを用いることで前置/後置を明確に区別しています。これらのキーワードは文脈依存キーワードとして導入されるため、既存コードとの互換性も保たれます。
これは新しい演算子を導入するものではなく、現在のインクリメント/デクリメント演算子オーバーロードの構文糖衣として導入されます。そのため、ABIを破損することはありません。
また、関数呼び出し形式で使用する際もprefix/postfixを使用できるようにすることを提案しています。。
S s; s.operator++ prefix(); s.operator++ postfix();
唯一の欠点としては、メンバ関数ポインタを取る際に現在のシグネチャが見えてしまうことだとしていますが、ここでもprefix/postfixを使用できるようにすることで緩和できるとしています。
// メンバ関数ポインタの取得 auto(S::* pre)() = &S::operator++; auto(S::* post)(int) = &S::operator++; // この提案による緩和案 auto pre = &S::operator++ prefix; auto post = &S::operator++ postfix; // これは次のように書いたのと等価 // auto(S::* tmp1)() = &S::operator++; // auto pre = tmp1; // auto(S::* tmp2)(int) = &S::operator++; // auto pre = tmp2;
とはいえ、インクリメント/デクリメント演算子のメンバ関数ポインタを取得することはかなり稀であるので、あまり問題にはなりません。
P3663R0 Future-proof submdspan-mapping?
submdsapn()がsubmdspan_mappingを呼び出す場合について、将来的な拡張を考慮しておくようにする提案。
submdsapn()はmdspanからサブスライスを取り出すための関数であり、第二引数以降で元のmdspanのエクステントにたいするスライス指定を渡します。この時、スライス指定はかなり柔軟に行うことができ、内部で適切なレイアウト変換などが行われます。
// なんか多次元配列 std::mdspan mat{...}; // 1行目の全列のスライス auto sub1 = std::submdspan(mat, 1, std::full_extent); // 1列目の全行のスライス auto sub2 = std::submdspan(mat, std::full_extent, 3); // 2x2の部分行列のスライス // 1行目から2行、2列目から3列 auto sub3 = std::submdspan(mat, std::pair{1, 3}, std::pair{2, 4});
submdspan()のスライス指定方法には4種類あります。Sをスライス指定の1次元分(可変長引数の一つ)とするとおおよそ次のような指定が可能です
Sはstd::full_extentに変換可能: その次元の全範囲を指定Sはindex-pair-like<index_type>のモデルとなる: その次元の特定の連続した範囲を指定Sはstrided_sliceの特殊化: その次元におけるオフセットと要素数、ストライドを指定Sはレイアウトマッピングクラスのindex_typeに変換可能: その次元の要素数を指定した値に固定
submdspan()は内部で入力mdspanのレイアウトマッピングに対するsubmdspan_mapping()を使用してレイアウト変換を行っており、これらのスライス指定に応じて新しいレイアウトのマッピングを求めています。
// submdspanの実装例(規格による効果の指定) // まずレイアウトマッピングを変換 auto sub_map_offset = submdspan_mapping(src.mapping(), args...); // mdspanを再構成 return mdspan(src.accessor().offset(src.data(), sub_map_offset.offset), sub_map_offset.mapping, AccessorPolicy::offset_policy(src.accessor()));
このように、現在の規定ではsubmdspan()に渡されたスライス指定をそのままsubmdspan_mapping()に渡してしまっています。規格ではsubmdspan_mapping(src.mapping(), slices...)がwell-formdとなる条件については指定しているもののill-formedとなる条件については指定していないため、有効なスライス指定入力に対してフィルタなしでsubmdspan_mapping()が呼ばれます。
これによって、次の場合に未定義動作が発生します
- C++26時点の
submdspan_mapping()のカスタマイズを使用して、ユーザー定義のレイアウトマッピングクラスmy_layout::mappingを作成する - C++29以降のバージョンで、
submdspan()に新しいスライス指定方法が追加される submdspan()が、新しいスライス指定方法とmy_layout::mappingについてのsubmdspan_mapping()を呼ぶ
ユーザー定義レイアウトマッピングクラスに対するsubmdspan_mapping()のカスタマイズはかなり複雑であるため、一部の形式だけをサポートして残りはしない(何らかのエラーにする)という実装を取ったり、全てをサポートしたつもりでも正しく書けていなかったりする可能性があります。あるいは、独自のスライス指定をサポートするようにカスタマイズすることもできます。このような場合、将来的に新しいスライス指定方法が追加された時にそれを間違って取り扱ってしまう可能性があります。
このような拡張はパディングストライドレイアウトの導入の際にすでに一度行われており、またP2819R2の採択によってstd::complexがpair-likeとなったほか、P2769R3ではtuple-likeの一般化(具体的な型のリストから、要件を満たす型の集合への拡張)が行われようとしています。
この提案は、この問題への対応のために、スライス指定を一旦正規化して正規化後のスライス型オブジェクトによってsubmdspan_mapping()を呼ぶようにすることを提案しています。
Sをスライス指定の1次元分(可変長引数の一つ)とすると、この正規化は次のように行われます
Sはレイアウトマッピングクラスのindex_typeに変換可能:canonical-ice<index_type>(s)Sはindex-pair-like<index_type>のモデルとなる:strided_slice{.offset=canonical-ice<index_type>(get<0>(s)), .extent=subtract-ice<index_type>(get<1>(s), get<0>(s)), .stride=cw<index_type(1)>}Sはstd::full_extentに変換可能:std::full_extentSはstrided_sliceの特殊化:strided_slice{.offset=canonical-ice<index_type>(s.offset), .extent=canonical-ice<index_type>(s.extent), .stride=canonical-ice<index_type>(s.stride)}
canonical-ice()とsubtract-ice()は説明専用の関数で、入力の定数性を維持したうえで、それをindex_typeまたはconstant_wrapper<Value, index_type>に変換するものです。
この正規化によって、ユーザー定義のものも含めたsubmdspan_mapping()は次の4種類の型のいずれかで呼ばれることが確実となります
- レイアウトマッピングクラスの
index_type constant_wrapper<Value, index_type>strided_slice- 各フィールドは1か2に相当するもの
full_extent_t
そして、これら以外の型の呼び出しはill-formedとすることができます。
これによるsubmdspan()の実装例は次のようになります
// スライス指定を正規化 auto [...canonicalize_slices] = submdspan_canonicalize_slices(src.extents(), slices...); // レイアウトマッピングを変換 auto sub_map_result = submdspan_mapping(src.mapping(), canonicalize_slices...); // mdspanを再構成 return mdspan(src.accessor().offset(src.data(), sub_map_result.offset), sub_map_result.mapping, AccessorPolicy::offset_policy(src.accessor()));
ただし、この提案はこのことをC++26への提案とはしておらず、submdspanの高品質な実装が自然に選択するアプローチであるとしています。この文書は
この問題について委員会に通知するとともに、委員会が修正を望んだ場合のための選択肢として提出されています。
P3664R0 Make variant_size SFINAE friendly
P2688R5のパターンマッチング提案では、std::anyに対するパターンマッチングが検討されています。
void f(const std::any& a) { a match { int: let i => ... double: let d => ... }; }
このようなマッチングにおいては他のマッチングも考慮したうえで使用される方法が決定され、std::anyの場合はtry_castを使用した方法によってマッチングが行われます。
しかし、std::variantに対するマッチング(代替パターンと呼ばれる)が先にチェックされるとvariant_size<remove_reference_t<decltype((e))>>のような型のチェックが行われ(variant_size<const std::any>のチェック)、variant_sizeの現在の設計ではこのような使用の正しさに関わらず入れ子型を定義しようとしてハードエラーになってしまいます。
これは構造化束縛とtuple_sizeにも同様の問題があったようで、その際にはtuple_sizeが入れ子型を適応的に定義するようにすることで解決されました。これによって::valueにアクセスするまではハードエラーを起こさなくなっています(これをSFINAE friendlyとここでは呼んでいる)。
この提案は、variant_sizeについても同様の改善を行おうとするものです。
- P2688R5 Pattern Matching:
matchExpression - WG21月次提案文書を眺める(2025年01月) - LWG Issue 2770.
tuple_size<const T>specialization is not SFINAE compatible and breaks decomposition declarations - P3664 進行状況