Compare commits

...

15 commits

Author SHA1 Message Date
Connector Switch
e456ba9196
Merge branch 'main' into users/c8ef/generator 2026-08-01 22:29:07 +08:00
Connector Switch
3841286280
Merge branch 'main' into users/c8ef/generator 2026-07-27 20:08:52 +08:00
Connector Switch
5f349af92c
Merge branch 'main' into users/c8ef/generator 2026-07-27 19:51:01 +08:00
Connector Switch
1dc74468ad
Merge branch 'main' into users/c8ef/generator 2026-07-22 18:18:26 +08:00
Connector Switch
1ff848a50f
Merge branch 'main' into users/c8ef/generator 2026-07-21 19:48:14 +08:00
c8ef
3e76eaccfc fix new warnings 2026-07-20 22:04:55 +08:00
c8ef
8fc0b82aeb release notes 23 -> 24 2026-07-20 20:22:23 +08:00
c8ef
90c7db7573 release notes 23 -> 24 2026-07-20 20:18:04 +08:00
c8ef
1a52064e92 Merge branch 'main' into users/c8ef/generator 2026-07-20 20:17:05 +08:00
c8ef
0b062c588a revert some transitive include change 2026-06-08 23:21:56 +08:00
c8ef
d4c2ae0fcc test 2026-06-05 23:57:26 +08:00
c8ef
57bf068697 test 2026-06-05 23:48:45 +08:00
c8ef
19e5608ff2 test 2026-06-05 23:27:41 +08:00
c8ef
f2ee26c784 release notes & python format 2026-06-05 22:52:35 +08:00
c8ef
22f5fee287 implement generator 2026-06-05 22:45:16 +08:00
23 changed files with 1113 additions and 15 deletions

View file

@ -344,6 +344,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_forward_like`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_generator`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_invoke_r`` ``202106L``
---------------------------------------------------------- -----------------
``__cpp_lib_ios_noreplace`` ``202207L``

View file

@ -45,6 +45,8 @@ Implemented Papers
- P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github <https://llvm.org/PR189606>`__)
- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github <https://llvm.org/PR105372>`__)
- P0528R3: The Curious Case of Padding Bits, Featuring Atomic Compare-and-Exchange (`Github <https://llvm.org/PR76180>`__)
- P2502R2: ``std::generator``: Synchronous Coroutine Generator for Ranges (`Github <https://llvm.org/PR105226>`__)
- P2787R1: ``pmr::generator`` - Promise Types are not Values (`Github <https://llvm.org/PR105263>`__)
Improvements and New Features
-----------------------------

View file

@ -217,7 +217,7 @@
"`LWG3759 <https://wg21.link/LWG3759>`__","``ranges::rotate_copy`` should use ``std::move``","2022-11 (Kona)","|Complete|","15","`#105027 <https://github.com/llvm/llvm-project/issues/105027>`__",""
"`LWG3760 <https://wg21.link/LWG3760>`__","``cartesian_product_view::iterator``'s ``parent_`` is never valid","2022-11 (Kona)","","","`#105028 <https://github.com/llvm/llvm-project/issues/105028>`__",""
"`LWG3761 <https://wg21.link/LWG3761>`__","``cartesian_product_view::iterator::operator-`` should pass by reference","2022-11 (Kona)","","","`#105029 <https://github.com/llvm/llvm-project/issues/105029>`__",""
"`LWG3762 <https://wg21.link/LWG3762>`__","``generator::iterator::operator==`` should pass by reference","2022-11 (Kona)","","","`#105030 <https://github.com/llvm/llvm-project/issues/105030>`__",""
"`LWG3762 <https://wg21.link/LWG3762>`__","``generator::iterator::operator==`` should pass by reference","2022-11 (Kona)","|Complete|","24","`#105030 <https://github.com/llvm/llvm-project/issues/105030>`__",""
"`LWG3764 <https://wg21.link/LWG3764>`__","``reference_wrapper::operator()`` should propagate noexcept","2022-11 (Kona)","|Complete|","17","`#105031 <https://github.com/llvm/llvm-project/issues/105031>`__",""
"`LWG3765 <https://wg21.link/LWG3765>`__","``const_sentinel`` should be constrained","2022-11 (Kona)","","","`#105032 <https://github.com/llvm/llvm-project/issues/105032>`__",""
"`LWG3766 <https://wg21.link/LWG3766>`__","``view_interface::cbegin`` is underconstrained","2022-11 (Kona)","","","`#105033 <https://github.com/llvm/llvm-project/issues/105033>`__",""

1 Issue # Issue Name Meeting Status First released version GitHub issue Notes
217 `LWG3759 <https://wg21.link/LWG3759>`__ ``ranges::rotate_copy`` should use ``std::move`` 2022-11 (Kona) |Complete| 15 `#105027 <https://github.com/llvm/llvm-project/issues/105027>`__
218 `LWG3760 <https://wg21.link/LWG3760>`__ ``cartesian_product_view::iterator``'s ``parent_`` is never valid 2022-11 (Kona) `#105028 <https://github.com/llvm/llvm-project/issues/105028>`__
219 `LWG3761 <https://wg21.link/LWG3761>`__ ``cartesian_product_view::iterator::operator-`` should pass by reference 2022-11 (Kona) `#105029 <https://github.com/llvm/llvm-project/issues/105029>`__
220 `LWG3762 <https://wg21.link/LWG3762>`__ ``generator::iterator::operator==`` should pass by reference 2022-11 (Kona) |Complete| 24 `#105030 <https://github.com/llvm/llvm-project/issues/105030>`__
221 `LWG3764 <https://wg21.link/LWG3764>`__ ``reference_wrapper::operator()`` should propagate noexcept 2022-11 (Kona) |Complete| 17 `#105031 <https://github.com/llvm/llvm-project/issues/105031>`__
222 `LWG3765 <https://wg21.link/LWG3765>`__ ``const_sentinel`` should be constrained 2022-11 (Kona) `#105032 <https://github.com/llvm/llvm-project/issues/105032>`__
223 `LWG3766 <https://wg21.link/LWG3766>`__ ``view_interface::cbegin`` is underconstrained 2022-11 (Kona) `#105033 <https://github.com/llvm/llvm-project/issues/105033>`__

View file

@ -80,7 +80,7 @@
"`P2474R2 <https://wg21.link/P2474R2>`__","``views::repeat``","2022-07 (Virtual)","|Complete|","17","`#105222 <https://github.com/llvm/llvm-project/issues/105222>`__",""
"`P2494R2 <https://wg21.link/P2494R2>`__","Relaxing range adaptors to allow for move only types","2022-07 (Virtual)","|Complete|","17","`#105224 <https://github.com/llvm/llvm-project/issues/105224>`__",""
"`P2499R0 <https://wg21.link/P2499R0>`__","``string_view`` range constructor should be ``explicit``","2022-07 (Virtual)","|Complete|","16","`#105225 <https://github.com/llvm/llvm-project/issues/105225>`__",""
"`P2502R2 <https://wg21.link/P2502R2>`__","``std::generator``: Synchronous Coroutine Generator for Ranges","2022-07 (Virtual)","","","`#105226 <https://github.com/llvm/llvm-project/issues/105226>`__",""
"`P2502R2 <https://wg21.link/P2502R2>`__","``std::generator``: Synchronous Coroutine Generator for Ranges","2022-07 (Virtual)","|Complete|","24","`#105226 <https://github.com/llvm/llvm-project/issues/105226>`__",""
"`P2508R1 <https://wg21.link/P2508R1>`__","Exposing ``std::basic-format-string``","2022-07 (Virtual)","|Complete|","15","`#105227 <https://github.com/llvm/llvm-project/issues/105227>`__",""
"`P2517R1 <https://wg21.link/P2517R1>`__","Add a conditional ``noexcept`` specification to ``std::apply``","2022-07 (Virtual)","|Complete|","3.9","`#105229 <https://github.com/llvm/llvm-project/issues/105229>`__",""
"`P2520R0 <https://wg21.link/P2520R0>`__","``move_iterator`` should be a random access iterator","2022-07 (Virtual)","|Complete|","17","`#105230 <https://github.com/llvm/llvm-project/issues/105230>`__","Implemented as a DR in C++20"
@ -115,7 +115,7 @@
"`P2674R1 <https://wg21.link/P2674R1>`__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20","`#105259 <https://github.com/llvm/llvm-project/issues/105259>`__",""
"`P2655R3 <https://wg21.link/P2655R3>`__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","|Complete|","21","`#105260 <https://github.com/llvm/llvm-project/issues/105260>`__","The paper is implemented as a DR to C++20"
"`P2652R2 <https://wg21.link/P2652R2>`__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19","`#105262 <https://github.com/llvm/llvm-project/issues/105262>`__",""
"`P2787R1 <https://wg21.link/P2787R1>`__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","","","`#105263 <https://github.com/llvm/llvm-project/issues/105263>`__",""
"`P2787R1 <https://wg21.link/P2787R1>`__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","|Complete|","24","`#105263 <https://github.com/llvm/llvm-project/issues/105263>`__",""
"`P2614R2 <https://wg21.link/P2614R2>`__","Deprecate ``numeric_limits::has_denorm``","2023-02 (Issaquah)","|Complete|","18","`#105264 <https://github.com/llvm/llvm-project/issues/105264>`__",""
"`P2588R3 <https://wg21.link/P2588R3>`__","``barrier``’s phase completion guarantees","2023-02 (Issaquah)","","","`#105265 <https://github.com/llvm/llvm-project/issues/105265>`__",""
"`P2763R1 <https://wg21.link/P2763R1>`__","``layout_stride`` static extents default constructor fix","2023-02 (Issaquah)","","","`#105266 <https://github.com/llvm/llvm-project/issues/105266>`__",""

1 Paper # Paper Name Meeting Status First released version GitHub issue Notes
80 `P2474R2 <https://wg21.link/P2474R2>`__ ``views::repeat`` 2022-07 (Virtual) |Complete| 17 `#105222 <https://github.com/llvm/llvm-project/issues/105222>`__
81 `P2494R2 <https://wg21.link/P2494R2>`__ Relaxing range adaptors to allow for move only types 2022-07 (Virtual) |Complete| 17 `#105224 <https://github.com/llvm/llvm-project/issues/105224>`__
82 `P2499R0 <https://wg21.link/P2499R0>`__ ``string_view`` range constructor should be ``explicit`` 2022-07 (Virtual) |Complete| 16 `#105225 <https://github.com/llvm/llvm-project/issues/105225>`__
83 `P2502R2 <https://wg21.link/P2502R2>`__ ``std::generator``: Synchronous Coroutine Generator for Ranges 2022-07 (Virtual) |Complete| 24 `#105226 <https://github.com/llvm/llvm-project/issues/105226>`__
84 `P2508R1 <https://wg21.link/P2508R1>`__ Exposing ``std::basic-format-string`` 2022-07 (Virtual) |Complete| 15 `#105227 <https://github.com/llvm/llvm-project/issues/105227>`__
85 `P2517R1 <https://wg21.link/P2517R1>`__ Add a conditional ``noexcept`` specification to ``std::apply`` 2022-07 (Virtual) |Complete| 3.9 `#105229 <https://github.com/llvm/llvm-project/issues/105229>`__
86 `P2520R0 <https://wg21.link/P2520R0>`__ ``move_iterator`` should be a random access iterator 2022-07 (Virtual) |Complete| 17 `#105230 <https://github.com/llvm/llvm-project/issues/105230>`__ Implemented as a DR in C++20
115 `P2674R1 <https://wg21.link/P2674R1>`__ A trait for implicit lifetime types 2023-02 (Issaquah) |Complete| 20 `#105259 <https://github.com/llvm/llvm-project/issues/105259>`__
116 `P2655R3 <https://wg21.link/P2655R3>`__ ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type 2023-02 (Issaquah) |Complete| 21 `#105260 <https://github.com/llvm/llvm-project/issues/105260>`__ The paper is implemented as a DR to C++20
117 `P2652R2 <https://wg21.link/P2652R2>`__ Disallow User Specialization of ``allocator_traits`` 2023-02 (Issaquah) |Complete| 19 `#105262 <https://github.com/llvm/llvm-project/issues/105262>`__
118 `P2787R1 <https://wg21.link/P2787R1>`__ ``pmr::generator`` - Promise Types are not Values 2023-02 (Issaquah) |Complete| 24 `#105263 <https://github.com/llvm/llvm-project/issues/105263>`__
119 `P2614R2 <https://wg21.link/P2614R2>`__ Deprecate ``numeric_limits::has_denorm`` 2023-02 (Issaquah) |Complete| 18 `#105264 <https://github.com/llvm/llvm-project/issues/105264>`__
120 `P2588R3 <https://wg21.link/P2588R3>`__ ``barrier``’s phase completion guarantees 2023-02 (Issaquah) `#105265 <https://github.com/llvm/llvm-project/issues/105265>`__
121 `P2763R1 <https://wg21.link/P2763R1>`__ ``layout_stride`` static extents default constructor fix 2023-02 (Issaquah) `#105266 <https://github.com/llvm/llvm-project/issues/105266>`__

View file

@ -4,7 +4,7 @@
"`LWG3885 <https://wg21.link/LWG3885>`__","``op`` should be in [zombie.names]","2023-06 (Varna)","|Nothing To Do|","","`#105270 <https://github.com/llvm/llvm-project/issues/105270>`__",""
"`LWG3887 <https://wg21.link/LWG3887>`__","Version macro for ``allocate_at_least``","2023-06 (Varna)","|Complete|","19","`#105271 <https://github.com/llvm/llvm-project/issues/105271>`__",""
"`LWG3893 <https://wg21.link/LWG3893>`__","LWG 3661 broke ``atomic<shared_ptr<T>> a; a = nullptr;``","2023-06 (Varna)","","","`#105273 <https://github.com/llvm/llvm-project/issues/105273>`__",""
"`LWG3894 <https://wg21.link/LWG3894>`__","``generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)`` should not be ``noexcept``","2023-06 (Varna)","","","`#105274 <https://github.com/llvm/llvm-project/issues/105274>`__",""
"`LWG3894 <https://wg21.link/LWG3894>`__","``generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)`` should not be ``noexcept``","2023-06 (Varna)","|Complete|","24","`#105274 <https://github.com/llvm/llvm-project/issues/105274>`__",""
"`LWG3903 <https://wg21.link/LWG3903>`__","span destructor is redundantly noexcept","2023-06 (Varna)","|Complete|","7","`#105275 <https://github.com/llvm/llvm-project/issues/105275>`__",""
"`LWG3904 <https://wg21.link/LWG3904>`__","``lazy_split_view::outer-iterator``'s const-converting constructor isn't setting ``trailing_empty_``","2023-06 (Varna)","","","`#105276 <https://github.com/llvm/llvm-project/issues/105276>`__",""
"`LWG3905 <https://wg21.link/LWG3905>`__","Type of ``std::fexcept_t``","2023-06 (Varna)","|Complete|","3.4","`#105277 <https://github.com/llvm/llvm-project/issues/105277>`__",""
@ -79,8 +79,8 @@
"`LWG3216 <https://wg21.link/LWG3216>`__","Rebinding the allocator before calling ``construct``/``destroy`` in ``allocate_shared``","2024-11 (Wrocław)","","","`#118332 <https://github.com/llvm/llvm-project/issues/118332>`__",""
"`LWG3436 <https://wg21.link/LWG3436>`__","``std::construct_at`` should support arrays","2024-11 (Wrocław)","","","`#118335 <https://github.com/llvm/llvm-project/issues/118335>`__",""
"`LWG3886 <https://wg21.link/LWG3886>`__","Monad mo' problems","2024-11 (Wrocław)","|Complete|","22","`#118336 <https://github.com/llvm/llvm-project/issues/118336>`__",""
"`LWG3899 <https://wg21.link/LWG3899>`__","``co_yield``\ing elements of an lvalue generator is unnecessarily inefficient","2024-11 (Wrocław)","","","`#118337 <https://github.com/llvm/llvm-project/issues/118337>`__",""
"`LWG3900 <https://wg21.link/LWG3900>`__","The ``allocator_arg_t`` overloads of ``generator::promise_type::operator new`` should not be constrained","2024-11 (Wrocław)","","","`#118338 <https://github.com/llvm/llvm-project/issues/118338>`__",""
"`LWG3899 <https://wg21.link/LWG3899>`__","``co_yield``\ing elements of an lvalue generator is unnecessarily inefficient","2024-11 (Wrocław)","|Complete|","24","`#118337 <https://github.com/llvm/llvm-project/issues/118337>`__",""
"`LWG3900 <https://wg21.link/LWG3900>`__","The ``allocator_arg_t`` overloads of ``generator::promise_type::operator new`` should not be constrained","2024-11 (Wrocław)","|Complete|","24","`#118338 <https://github.com/llvm/llvm-project/issues/118338>`__",""
"`LWG3918 <https://wg21.link/LWG3918>`__","``std::uninitialized_move/_n`` and guaranteed copy elision","2024-11 (Wrocław)","|Complete|","23","`#118339 <https://github.com/llvm/llvm-project/issues/118339>`__",""
"`LWG4014 <https://wg21.link/LWG4014>`__","LWG 3809 changes behavior of some existing ``std::subtract_with_carry_engine code``","2024-11 (Wrocław)","","","`#118340 <https://github.com/llvm/llvm-project/issues/118340>`__",""
"`LWG4024 <https://wg21.link/LWG4024>`__","Underspecified destruction of objects created in ``std::make_shared_for_overwrite``/``std::allocate_shared_for_overwrite``","2024-11 (Wrocław)","|Complete|","16","`#118341 <https://github.com/llvm/llvm-project/issues/118341>`__",""
@ -93,7 +93,7 @@
"`LWG4088 <https://wg21.link/LWG4088>`__","``println`` ignores the locale imbued in ``std::ostream``","2024-11 (Wrocław)","|Complete|","18","`#118348 <https://github.com/llvm/llvm-project/issues/118348>`__",""
"`LWG4112 <https://wg21.link/LWG4112>`__","``has-arrow`` should required ``operator->()`` to be ``const``-qualified","2024-11 (Wrocław)","","","`#118349 <https://github.com/llvm/llvm-project/issues/118349>`__",""
"`LWG4113 <https://wg21.link/LWG4113>`__","Disallow ``has_unique_object_representations<Incomplete[]>``","2024-11 (Wrocław)","|Complete|","","`#118350 <https://github.com/llvm/llvm-project/issues/118350>`__",""
"`LWG4119 <https://wg21.link/LWG4119>`__","``generator::promise_type::yield_value(ranges::elements_of<R, Alloc>)``'s nested ``generator`` may be ill-formed","2024-11 (Wrocław)","","","`#118351 <https://github.com/llvm/llvm-project/issues/118351>`__",""
"`LWG4119 <https://wg21.link/LWG4119>`__","``generator::promise_type::yield_value(ranges::elements_of<R, Alloc>)``'s nested ``generator`` may be ill-formed","2024-11 (Wrocław)","|Complete|","24","`#118351 <https://github.com/llvm/llvm-project/issues/118351>`__",""
"`LWG4124 <https://wg21.link/LWG4124>`__","Cannot format ``zoned_time`` with resolution coarser than ``seconds``","2024-11 (Wrocław)","","","`#118352 <https://github.com/llvm/llvm-project/issues/118352>`__",""
"`LWG4126 <https://wg21.link/LWG4126>`__","Some feature-test macros for fully freestanding features are not yet marked freestanding","2024-11 (Wrocław)","","","`#118353 <https://github.com/llvm/llvm-project/issues/118353>`__",""
"`LWG4134 <https://wg21.link/LWG4134>`__","Issue with Philox algorithm specification","2024-11 (Wrocław)","","","`#118354 <https://github.com/llvm/llvm-project/issues/118354>`__",""

1 Issue # Issue Name Meeting Status First released version GitHub issue Notes
4 `LWG3885 <https://wg21.link/LWG3885>`__ ``op`` should be in [zombie.names] 2023-06 (Varna) |Nothing To Do| `#105270 <https://github.com/llvm/llvm-project/issues/105270>`__
5 `LWG3887 <https://wg21.link/LWG3887>`__ Version macro for ``allocate_at_least`` 2023-06 (Varna) |Complete| 19 `#105271 <https://github.com/llvm/llvm-project/issues/105271>`__
6 `LWG3893 <https://wg21.link/LWG3893>`__ LWG 3661 broke ``atomic<shared_ptr<T>> a; a = nullptr;`` 2023-06 (Varna) `#105273 <https://github.com/llvm/llvm-project/issues/105273>`__
7 `LWG3894 <https://wg21.link/LWG3894>`__ ``generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)`` should not be ``noexcept`` 2023-06 (Varna) |Complete| 24 `#105274 <https://github.com/llvm/llvm-project/issues/105274>`__
8 `LWG3903 <https://wg21.link/LWG3903>`__ span destructor is redundantly noexcept 2023-06 (Varna) |Complete| 7 `#105275 <https://github.com/llvm/llvm-project/issues/105275>`__
9 `LWG3904 <https://wg21.link/LWG3904>`__ ``lazy_split_view::outer-iterator``'s const-converting constructor isn't setting ``trailing_empty_`` 2023-06 (Varna) `#105276 <https://github.com/llvm/llvm-project/issues/105276>`__
10 `LWG3905 <https://wg21.link/LWG3905>`__ Type of ``std::fexcept_t`` 2023-06 (Varna) |Complete| 3.4 `#105277 <https://github.com/llvm/llvm-project/issues/105277>`__
79 `LWG3216 <https://wg21.link/LWG3216>`__ Rebinding the allocator before calling ``construct``/``destroy`` in ``allocate_shared`` 2024-11 (Wrocław) `#118332 <https://github.com/llvm/llvm-project/issues/118332>`__
80 `LWG3436 <https://wg21.link/LWG3436>`__ ``std::construct_at`` should support arrays 2024-11 (Wrocław) `#118335 <https://github.com/llvm/llvm-project/issues/118335>`__
81 `LWG3886 <https://wg21.link/LWG3886>`__ Monad mo' problems 2024-11 (Wrocław) |Complete| 22 `#118336 <https://github.com/llvm/llvm-project/issues/118336>`__
82 `LWG3899 <https://wg21.link/LWG3899>`__ ``co_yield``\ing elements of an lvalue generator is unnecessarily inefficient 2024-11 (Wrocław) |Complete| 24 `#118337 <https://github.com/llvm/llvm-project/issues/118337>`__
83 `LWG3900 <https://wg21.link/LWG3900>`__ The ``allocator_arg_t`` overloads of ``generator::promise_type::operator new`` should not be constrained 2024-11 (Wrocław) |Complete| 24 `#118338 <https://github.com/llvm/llvm-project/issues/118338>`__
84 `LWG3918 <https://wg21.link/LWG3918>`__ ``std::uninitialized_move/_n`` and guaranteed copy elision 2024-11 (Wrocław) |Complete| 23 `#118339 <https://github.com/llvm/llvm-project/issues/118339>`__
85 `LWG4014 <https://wg21.link/LWG4014>`__ LWG 3809 changes behavior of some existing ``std::subtract_with_carry_engine code`` 2024-11 (Wrocław) `#118340 <https://github.com/llvm/llvm-project/issues/118340>`__
86 `LWG4024 <https://wg21.link/LWG4024>`__ Underspecified destruction of objects created in ``std::make_shared_for_overwrite``/``std::allocate_shared_for_overwrite`` 2024-11 (Wrocław) |Complete| 16 `#118341 <https://github.com/llvm/llvm-project/issues/118341>`__
93 `LWG4088 <https://wg21.link/LWG4088>`__ ``println`` ignores the locale imbued in ``std::ostream`` 2024-11 (Wrocław) |Complete| 18 `#118348 <https://github.com/llvm/llvm-project/issues/118348>`__
94 `LWG4112 <https://wg21.link/LWG4112>`__ ``has-arrow`` should required ``operator->()`` to be ``const``-qualified 2024-11 (Wrocław) `#118349 <https://github.com/llvm/llvm-project/issues/118349>`__
95 `LWG4113 <https://wg21.link/LWG4113>`__ Disallow ``has_unique_object_representations<Incomplete[]>`` 2024-11 (Wrocław) |Complete| `#118350 <https://github.com/llvm/llvm-project/issues/118350>`__
96 `LWG4119 <https://wg21.link/LWG4119>`__ ``generator::promise_type::yield_value(ranges::elements_of<R, Alloc>)``'s nested ``generator`` may be ill-formed 2024-11 (Wrocław) |Complete| 24 `#118351 <https://github.com/llvm/llvm-project/issues/118351>`__
97 `LWG4124 <https://wg21.link/LWG4124>`__ Cannot format ``zoned_time`` with resolution coarser than ``seconds`` 2024-11 (Wrocław) `#118352 <https://github.com/llvm/llvm-project/issues/118352>`__
98 `LWG4126 <https://wg21.link/LWG4126>`__ Some feature-test macros for fully freestanding features are not yet marked freestanding 2024-11 (Wrocław) `#118353 <https://github.com/llvm/llvm-project/issues/118353>`__
99 `LWG4134 <https://wg21.link/LWG4134>`__ Issue with Philox algorithm specification 2024-11 (Wrocław) `#118354 <https://github.com/llvm/llvm-project/issues/118354>`__

View file

@ -1059,6 +1059,7 @@ set(files
fstream
functional
future
generator
initializer_list
iomanip
ios

614
libcxx/include/generator Normal file
View file

@ -0,0 +1,614 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_GENERATOR
#define _LIBCPP_GENERATOR
/*
namespace std {
// [coro.generator.class], class template generator
template<class Ref, class Val = void, class Allocator = void>
class generator;
namespace pmr {
template<class Ref, class Val = void>
using generator = std::generator<Ref, Val, polymorphic_allocator<>>;
}
}
*/
#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
# include <__cxx03/__config>
#else
# include <__config>
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
# endif
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
# if _LIBCPP_STD_VER >= 23
# include <__algorithm/max.h>
# include <__assert>
# include <__concepts/common_reference_with.h>
# include <__concepts/constructible.h>
# include <__concepts/convertible_to.h>
# include <__concepts/same_as.h>
# include <__coroutine/coroutine_handle.h>
# include <__coroutine/coroutine_traits.h>
# include <__coroutine/noop_coroutine_handle.h>
# include <__coroutine/trivial_awaitables.h>
# include <__exception/exception_ptr.h>
# include <__iterator/default_sentinel.h>
# include <__memory/addressof.h>
# include <__memory/allocator_arg_t.h>
# include <__memory/allocator_traits.h>
# include <__memory/construct_at.h>
# include <__memory_resource/polymorphic_allocator.h>
# include <__ranges/access.h>
# include <__ranges/concepts.h>
# include <__ranges/elements_of.h>
# include <__ranges/view_interface.h>
# include <__type_traits/add_pointer.h>
# include <__type_traits/common_reference.h>
# include <__type_traits/conditional.h>
# include <__type_traits/is_nothrow_constructible.h>
# include <__type_traits/is_object.h>
# include <__type_traits/is_pointer.h>
# include <__type_traits/is_reference.h>
# include <__type_traits/is_void.h>
# include <__type_traits/remove_cvref.h>
# include <__type_traits/remove_reference.h>
# include <__utility/exchange.h>
# include <__utility/move.h>
# include <__utility/swap.h>
# include <cstdint>
# include <new>
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Ref, class _Val>
using __gen_val _LIBCPP_NODEBUG = conditional_t<is_void_v<_Val>, remove_cvref_t<_Ref>, _Val>;
template <class _Ref, class _Val>
using __gen_ref _LIBCPP_NODEBUG = conditional_t<is_void_v<_Val>, _Ref&&, _Ref>;
template <class _Ref, class _Val>
using __gen_yielded _LIBCPP_NODEBUG =
conditional_t<is_reference_v<__gen_ref<_Ref, _Val>>, __gen_ref<_Ref, _Val>, const __gen_ref<_Ref, _Val>&>;
template <class, class>
struct __gen_iter_provider {
class __iterator;
};
template <class, class, class>
class generator;
template <class _Yielded>
class __gen_promise_base {
private:
template <class, class, class>
friend class generator;
template <class, class>
friend struct __gen_iter_provider;
// Each promise object stores either a `__root_data` when associated with a root generator, or a `__recursive_data`
// when associated with a generator that is yielded recursively.
struct __root_data {
// The client code has access only to the iterator of the root generator. Thus, the root generator must store the
// yielded values of recursively-yielded generators, which will then be returned when the client code dereferences
// the iterator.
add_pointer_t<_Yielded> __value_ptr;
// The client code has access only to the iterator of the root generator. Thus, the root generator needs to identify
// which generator is currently active. This active generator will then be resumed when the client code increments
// the iterator.
coroutine_handle<__gen_promise_base> __active;
};
struct __recursive_data {
exception_ptr __exception;
coroutine_handle<__gen_promise_base> __parent;
coroutine_handle<__gen_promise_base> __root;
};
union __union {
__root_data __root;
__recursive_data __recursive;
_LIBCPP_HIDE_FROM_ABI ~__union() noexcept {}
} __data_;
// The `__tag_` stores the active member of the `__data_` union:
// - `false` indicates that the active member is `__root`.
// - `true` indicates that the active member is `__recursive`.
// This field can be omitted because `__recursive_data.__root` can store the active member.
bool __tag_;
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_root() noexcept { return !__tag_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __root_data& __get_root_data() noexcept {
_LIBCPP_ASSERT_INTERNAL(__is_root(), "the active member of `__data_` is not `__root`");
return __data_.__root;
}
_LIBCPP_HIDE_FROM_ABI void __set_root_tag() noexcept { __tag_ = false; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_recursive() noexcept { return __tag_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __recursive_data& __get_recursive_data() noexcept {
_LIBCPP_ASSERT_INTERNAL(__is_recursive(), "the active member of `__data_` is not `__recursive`");
return __data_.__recursive;
}
_LIBCPP_HIDE_FROM_ABI void __set_recursive_tag() noexcept { __tag_ = true; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI coroutine_handle<__gen_promise_base>& __active() noexcept {
_LIBCPP_ASSERT_INTERNAL(__is_root(), "the active member of `__data_` is not `__root`");
return __get_root_data().__active;
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI add_pointer_t<_Yielded>& __value_ptr() noexcept {
_LIBCPP_ASSERT_INTERNAL(__is_root(), "the active member of `__data_` is not `__root`");
return __get_root_data().__value_ptr;
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI add_pointer_t<_Yielded>& __root_value_ptr() noexcept {
if (__is_root()) {
return __value_ptr();
}
return __get_recursive_data().__root.promise().__value_ptr();
}
struct __element_awaiter {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool await_ready() noexcept { return false; }
template <class _Promise>
_LIBCPP_HIDE_FROM_ABI void await_suspend(coroutine_handle<_Promise> __current) noexcept {
__current.promise().__root_value_ptr() = std::addressof(__value);
}
_LIBCPP_HIDE_FROM_ABI void await_resume() noexcept {}
remove_cvref_t<_Yielded> __value;
};
struct __final_awaiter {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool await_ready() noexcept { return false; }
template <class _Promise>
_LIBCPP_HIDE_FROM_ABI coroutine_handle<> await_suspend(coroutine_handle<_Promise> __current) noexcept {
// Checks if the current generator is recursively-yielded
if (__current.promise().__is_recursive()) {
auto&& __recursive_data = __current.promise().__get_recursive_data();
auto __parent = __recursive_data.__parent;
// Updates the active generator to its parent, allowing the client code to resume it later
__recursive_data.__root.promise().__active() = __parent;
// Transfers execution to its parent, which is the generator that yields it
return __parent;
}
return std::noop_coroutine();
}
_LIBCPP_HIDE_FROM_ABI void await_resume() noexcept {}
};
template <class _Ref, class _Val, class _Allocator>
struct __recursive_awaiter {
_LIBCPP_HIDE_FROM_ABI explicit __recursive_awaiter(generator<_Ref, _Val, _Allocator>&& __gen) noexcept
: __gen_{std::move(__gen)} {}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool await_ready() noexcept { return !__gen_.__coroutine_; }
template <class _Promise>
_LIBCPP_HIDE_FROM_ABI coroutine_handle<__gen_promise_base>
await_suspend(coroutine_handle<_Promise> __current) noexcept {
// Stores a `__recursive_data` in the promise object associated with `__gen`
auto __recursive = coroutine_handle<__gen_promise_base>::from_address(__gen_.__coroutine_.address());
__recursive.promise().__set_recursive_tag();
auto&& __recursive_data = __recursive.promise().__get_recursive_data();
// Sets `__recursive_data.__parent` to the current generator
auto __parent = coroutine_handle<__gen_promise_base>::from_address(__current.address());
__recursive_data.__parent = __parent;
// Sets `__recursive_data.__root` to the current generator if it's a root generator, or to the root generator of
// the current generator otherwise
if (__parent.promise().__is_recursive()) {
__recursive_data.__root = __parent.promise().__get_recursive_data().__root;
} else {
__recursive_data.__root = __parent;
}
// Updates the active generator to `__gen`, allowing the client code to resume it later
__recursive_data.__root.promise().__active() = __recursive;
// Transfers execution to `__gen`
return __recursive;
}
_LIBCPP_HIDE_FROM_ABI void await_resume() {
auto __recursive = coroutine_handle<__gen_promise_base>::from_address(__gen_.__coroutine_.address());
auto&& __recursive_data = __recursive.promise().__get_recursive_data();
if (__recursive_data.__exception) {
std::rethrow_exception(std::move(__recursive_data.__exception));
}
}
private:
generator<_Ref, _Val, _Allocator> __gen_;
};
public:
_LIBCPP_HIDE_FROM_ABI __gen_promise_base() noexcept
: __data_{.__root{
.__value_ptr{nullptr},
.__active{coroutine_handle<__gen_promise_base>::from_promise(*this)},
}},
__tag_{false} {}
_LIBCPP_HIDE_FROM_ABI ~__gen_promise_base() noexcept {
if (__is_root()) {
__data_.__root.~__root_data();
} else {
__data_.__recursive.~__recursive_data();
}
}
_LIBCPP_HIDE_FROM_ABI suspend_always initial_suspend() const noexcept { return {}; }
_LIBCPP_HIDE_FROM_ABI __final_awaiter final_suspend() noexcept { return {}; }
_LIBCPP_HIDE_FROM_ABI suspend_always yield_value(_Yielded __value) noexcept {
__root_value_ptr() = std::addressof(__value);
return {};
}
_LIBCPP_HIDE_FROM_ABI auto yield_value(const remove_reference_t<_Yielded>& __value) noexcept(
is_nothrow_constructible_v<remove_cvref_t<_Yielded>, const remove_reference_t<_Yielded>&>)
requires is_rvalue_reference_v<_Yielded> &&
constructible_from<remove_cvref_t<_Yielded>, const remove_reference_t<_Yielded>&>
{
return __element_awaiter{.__value{__value}};
}
template <class _Ref2, class _Val2, class _Allocator2, class _Unused>
requires same_as<__gen_yielded<_Ref2, _Val2>, _Yielded>
_LIBCPP_HIDE_FROM_ABI auto
yield_value(ranges::elements_of<generator<_Ref2, _Val2, _Allocator2>&&, _Unused> __elements) noexcept {
return __recursive_awaiter<_Ref2, _Val2, _Allocator2>{std::move(__elements.range)};
}
template <class _Ref2, class _Val2, class _Allocator2, class _Unused>
requires same_as<__gen_yielded<_Ref2, _Val2>, _Yielded>
_LIBCPP_HIDE_FROM_ABI auto
yield_value(ranges::elements_of<generator<_Ref2, _Val2, _Allocator2>&, _Unused> __elements) noexcept {
return __recursive_awaiter<_Ref2, _Val2, _Allocator2>{std::move(__elements.range)};
}
template <ranges::input_range _Range, class _Allocator>
requires convertible_to<ranges::range_reference_t<_Range>, _Yielded>
_LIBCPP_HIDE_FROM_ABI auto yield_value(ranges::elements_of<_Range, _Allocator> __range) {
auto __lambda =
[](allocator_arg_t, _Allocator, ranges::iterator_t<_Range> __i, ranges::sentinel_t<_Range> __s) static
-> generator<_Yielded, void, _Allocator> {
for (; __i != __s; ++__i) {
co_yield static_cast<_Yielded>(*__i);
}
};
return yield_value(ranges::elements_of(
__lambda(allocator_arg, __range.allocator, ranges::begin(__range.range), ranges::end(__range.range))));
}
_LIBCPP_HIDE_FROM_ABI void await_transform() = delete;
_LIBCPP_HIDE_FROM_ABI void return_void() const noexcept {}
_LIBCPP_HIDE_FROM_ABI void unhandled_exception() {
# if _LIBCPP_HAS_EXCEPTIONS
if (__is_root()) {
throw;
} else {
__get_recursive_data().__exception = std::current_exception();
}
# endif
}
};
struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) __gen_aligned_block {
char __data[__STDCPP_DEFAULT_NEW_ALIGNMENT__];
_LIBCPP_HIDE_FROM_ABI static size_t __count(const size_t __size) noexcept {
return (__size + sizeof(__gen_aligned_block) - 1) / sizeof(__gen_aligned_block);
}
};
template <class _Allocator>
concept __gen_stateless_allocator =
default_initializable<_Allocator> && allocator_traits<_Allocator>::is_always_equal::value;
template <class _Allocator>
class __gen_promise_allocator {
private:
using __rebind _LIBCPP_NODEBUG = allocator_traits<_Allocator>::template rebind_alloc<__gen_aligned_block>;
using __rebind_size_type _LIBCPP_NODEBUG = allocator_traits<__rebind>::size_type;
using __rebind_pointer _LIBCPP_NODEBUG = allocator_traits<__rebind>::pointer;
static_assert(is_pointer_v<__rebind_pointer>);
_LIBCPP_HIDE_FROM_ABI static void* __alloc(const _Allocator& __al, size_t __size) {
__rebind __rebind_al = static_cast<__rebind>(__al);
if constexpr (__gen_stateless_allocator<__rebind>) {
const size_t __block_count = __gen_aligned_block::__count(__size);
return __rebind_al.allocate(static_cast<__rebind_size_type>(__block_count));
} else {
// Allocates enough blocks for the coroutine frame, the size of the stateful allocator, and the alignment of the
// stateful allocator
const size_t __block_count = __gen_aligned_block::__count(__size + sizeof(__rebind) + alignof(__rebind));
void* const __ptr = __rebind_al.allocate(static_cast<__rebind_size_type>(__block_count));
// Stores the stateful allocator in the allocated block
__rebind* const __rebind_al_ptr = reinterpret_cast<__rebind*>(
(reinterpret_cast<uintptr_t>(__ptr) + __size + alignof(__rebind) - 1) & ~(alignof(__rebind) - 1));
std::construct_at(__rebind_al_ptr, std::move(__rebind_al));
return __ptr;
}
}
public:
_LIBCPP_HIDE_FROM_ABI void* operator new(size_t __size)
requires default_initializable<_Allocator>
{
return __alloc({}, __size);
}
template <class _Allocator2, class... _Args>
_LIBCPP_HIDE_FROM_ABI void* operator new(size_t __size, allocator_arg_t, const _Allocator2& __al, const _Args&...) {
return __alloc(static_cast<_Allocator>(__al), __size);
}
template <class _This, class _Allocator2, class... _Args>
_LIBCPP_HIDE_FROM_ABI void*
operator new(size_t __size, const _This&, allocator_arg_t, const _Allocator2& __al, const _Args&...) {
return __alloc(static_cast<_Allocator>(__al), __size);
}
_LIBCPP_HIDE_FROM_ABI static void operator delete(void* const __ptr, size_t __size) noexcept {
if constexpr (__gen_stateless_allocator<__rebind>) {
__rebind __rebind_al;
const size_t __block_count = __gen_aligned_block::__count(__size);
__rebind_al.deallocate(static_cast<__gen_aligned_block*>(__ptr), static_cast<__rebind_size_type>(__block_count));
} else {
// Retrieves the stateful allocator stored in the allocated block
__rebind* const __rebind_al_ptr = reinterpret_cast<__rebind*>(
(reinterpret_cast<uintptr_t>(__ptr) + __size + alignof(__rebind) - 1) & ~(alignof(__rebind) - 1));
__rebind __rebind_al = std::move(*__rebind_al_ptr);
std::destroy_at(__rebind_al_ptr);
const size_t __block_count = __gen_aligned_block::__count(__size + sizeof(__rebind) + alignof(__rebind));
__rebind_al.deallocate(static_cast<__gen_aligned_block*>(__ptr), static_cast<__rebind_size_type>(__block_count));
}
}
};
template <>
class __gen_promise_allocator<void> {
private:
using __dealloc_fn _LIBCPP_NODEBUG = void (*)(void*, size_t) noexcept;
template <class _Allocator>
_LIBCPP_HIDE_FROM_ABI static void* __alloc(const _Allocator& __al, size_t __size) {
using __rebind = allocator_traits<_Allocator>::template rebind_alloc<__gen_aligned_block>;
using __rebind_size_type = allocator_traits<__rebind>::size_type;
using __rebind_pointer = allocator_traits<__rebind>::pointer;
static_assert(is_pointer_v<__rebind_pointer>);
__rebind __rebind_al = static_cast<__rebind>(__al);
if constexpr (__gen_stateless_allocator<__rebind>) {
const size_t __block_count = __gen_aligned_block::__count(__size + sizeof(__dealloc_fn));
void* const __ptr = __rebind_al.allocate(static_cast<__rebind_size_type>(__block_count));
// Stores the deallocation function in the allocated block
__dealloc_fn* const __dealloc_ptr = reinterpret_cast<__dealloc_fn*>(reinterpret_cast<uintptr_t>(__ptr) + __size);
*__dealloc_ptr = __dealloc<__rebind>;
return __ptr;
} else {
// Allocates enough blocks for the coroutine frame, the size of the stateful allocator, the alignment of the
// stateful allocator, and the deallocation function
const size_t __block_count =
__gen_aligned_block::__count(__size + sizeof(__dealloc_fn) + sizeof(__rebind) + alignof(__rebind));
void* const __ptr = __rebind_al.allocate(static_cast<__rebind_size_type>(__block_count));
// Stores the deallocation function in the allocated block
__dealloc_fn* const __dealloc_ptr = reinterpret_cast<__dealloc_fn*>(reinterpret_cast<uintptr_t>(__ptr) + __size);
*__dealloc_ptr = __dealloc<__rebind>;
// Stores the stateful allocator in the allocated block
__rebind* const __rebind_al_ptr = reinterpret_cast<__rebind*>(
(reinterpret_cast<uintptr_t>(__ptr) + sizeof(__dealloc_fn) + __size + alignof(__rebind) - 1) &
~(alignof(__rebind) - 1));
std::construct_at(__rebind_al_ptr, std::move(__rebind_al));
return __ptr;
}
}
template <class _Rebind>
_LIBCPP_HIDE_FROM_ABI static void __dealloc(void* const __ptr, size_t __size) noexcept {
using __rebind_size_type = allocator_traits<_Rebind>::size_type;
if constexpr (__gen_stateless_allocator<_Rebind>) {
_Rebind __rebind_al;
const size_t __block_count = __gen_aligned_block::__count(__size + sizeof(__dealloc_fn));
__rebind_al.deallocate(static_cast<__gen_aligned_block*>(__ptr), static_cast<__rebind_size_type>(__block_count));
} else {
// Retrieves the stateful allocator stored in the allocated block
_Rebind* const __rebind_al_ptr = reinterpret_cast<_Rebind*>(
(reinterpret_cast<uintptr_t>(__ptr) + __size + sizeof(__dealloc_fn) + alignof(_Rebind) - 1) &
~(alignof(_Rebind) - 1));
_Rebind __rebind_al = std::move(*__rebind_al_ptr);
std::destroy_at(__rebind_al_ptr);
const size_t __block_count =
__gen_aligned_block::__count(__size + sizeof(__dealloc_fn) + sizeof(_Rebind) + alignof(_Rebind));
__rebind_al.deallocate(static_cast<__gen_aligned_block*>(__ptr), static_cast<__rebind_size_type>(__block_count));
}
}
public:
_LIBCPP_HIDE_FROM_ABI void* operator new(size_t __size) {
void* const __ptr = ::operator new(__size + sizeof(__dealloc_fn));
__dealloc_fn __dealloc =
[](void* const __dealloc_ptr, [[maybe_unused]] const size_t __dealloc_size) static noexcept -> void {
# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
::operator delete(__dealloc_ptr, __dealloc_size + sizeof(__dealloc_fn));
# else
::operator delete(__dealloc_ptr);
# endif
};
__dealloc_fn* const __dealloc_ptr = reinterpret_cast<__dealloc_fn*>(reinterpret_cast<uintptr_t>(__ptr) + __size);
*__dealloc_ptr = __dealloc;
return __ptr;
}
template <class _Allocator, class... _Args>
_LIBCPP_HIDE_FROM_ABI void* operator new(size_t __size, allocator_arg_t, const _Allocator& __al, const _Args&...) {
return __alloc(__al, __size);
}
template <class _This, class _Allocator, class... _Args>
_LIBCPP_HIDE_FROM_ABI void*
operator new(size_t __size, const _This&, allocator_arg_t, const _Allocator& __al, const _Args&...) {
return __alloc(__al, __size);
}
_LIBCPP_HIDE_FROM_ABI static void operator delete(void* const __ptr, size_t __size) noexcept {
__dealloc_fn* const __dealloc_ptr = reinterpret_cast<__dealloc_fn*>(reinterpret_cast<uintptr_t>(__ptr) + __size);
const __dealloc_fn __dealloc = *__dealloc_ptr;
__dealloc(__ptr, __size);
}
};
template <class _Ref, class _Val>
class __gen_iter_provider<_Ref, _Val>::__iterator {
private:
using __val _LIBCPP_NODEBUG = __gen_val<_Ref, _Val>;
using __ref _LIBCPP_NODEBUG = __gen_ref<_Ref, _Val>;
public:
using value_type = __val;
using difference_type = ptrdiff_t;
_LIBCPP_HIDE_FROM_ABI explicit __iterator(
coroutine_handle<__gen_promise_base<__gen_yielded<_Ref, _Val>>> __coroutine) noexcept
: __coroutine_{__coroutine} {}
_LIBCPP_HIDE_FROM_ABI __iterator(__iterator&& __other) noexcept
: __coroutine_{std::exchange(__other.__coroutine_, {})} {}
_LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&& __other) noexcept {
__coroutine_ = std::exchange(__other.__coroutine_, {});
return *this;
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __ref operator*() const noexcept(is_nothrow_copy_constructible_v<__ref>) {
return static_cast<__ref>(*__coroutine_.promise().__value_ptr());
}
_LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
__coroutine_.promise().__active().resume();
return *this;
}
_LIBCPP_HIDE_FROM_ABI void operator++(int) { ++*this; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __iter, default_sentinel_t) noexcept {
return __iter.__coroutine_.done();
}
private:
coroutine_handle<__gen_promise_base<__gen_yielded<_Ref, _Val>>> __coroutine_;
};
template <class _Ref, class _Val = void, class _Allocator = void>
class generator : public ranges::view_interface<generator<_Ref, _Val, _Allocator>> {
private:
using __val _LIBCPP_NODEBUG = __gen_val<_Ref, _Val>;
static_assert(same_as<remove_cvref_t<__val>, __val> && is_object_v<__val>);
using __ref _LIBCPP_NODEBUG = __gen_ref<_Ref, _Val>;
static_assert(is_reference_v<__ref> ||
(same_as<remove_cvref_t<__ref>, __ref> && is_object_v<__ref> && copy_constructible<__ref>));
using __rref _LIBCPP_NODEBUG = conditional_t<is_lvalue_reference_v<_Ref>, remove_reference_t<_Ref>&&, _Ref>;
static_assert(common_reference_with<__ref&&, __val&> && common_reference_with<__ref&&, __rref&&> &&
common_reference_with<__rref&&, const __val&>);
template <class>
friend class __gen_promise_base;
public:
using yielded = __gen_yielded<_Ref, _Val>;
struct promise_type : __gen_promise_base<yielded>, __gen_promise_allocator<_Allocator> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI generator get_return_object() noexcept {
return generator{coroutine_handle<promise_type>::from_promise(*this)};
}
};
_LIBCPP_HIDE_FROM_ABI generator(const generator&) = delete;
_LIBCPP_HIDE_FROM_ABI generator(generator&& __other) noexcept
: __coroutine_{std::exchange(__other.__coroutine_, {})} {}
_LIBCPP_HIDE_FROM_ABI ~generator() {
if (__coroutine_) {
__coroutine_.destroy();
}
}
_LIBCPP_HIDE_FROM_ABI generator& operator=(generator __other) noexcept {
std::swap(__coroutine_, __other.__coroutine_);
return *this;
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __gen_iter_provider<_Ref, _Val>::__iterator begin() {
auto __coroutine = coroutine_handle<__gen_promise_base<yielded>>::from_promise(__coroutine_.promise());
__coroutine.resume();
return typename __gen_iter_provider<_Ref, _Val>::__iterator{__coroutine};
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI default_sentinel_t end() const noexcept { return {}; }
private:
_LIBCPP_HIDE_FROM_ABI explicit generator(coroutine_handle<promise_type> __coroutine) noexcept
: __coroutine_{__coroutine} {}
coroutine_handle<promise_type> __coroutine_;
};
namespace pmr {
template <class _Ref, class _Val = void>
using generator = std::generator<_Ref, _Val, polymorphic_allocator<>>;
} // namespace pmr
_LIBCPP_END_NAMESPACE_STD
# endif // _LIBCPP_STD_VER >= 23
_LIBCPP_POP_MACROS
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#endif // _LIBCPP_GENERATOR

View file

@ -1483,6 +1483,11 @@ module std {
export *
}
module generator {
header "generator"
export *
}
module iomanip {
header "iomanip"
export *

View file

@ -134,6 +134,7 @@ __cpp_lib_fstream_native_handle 202306L <fstream>
__cpp_lib_function_ref 202603L <functional>
__cpp_lib_gcd_lcm 201606L <numeric>
__cpp_lib_generate_random 202403L <random>
__cpp_lib_generator 202207L <generator>
__cpp_lib_generic_associative_lookup 201304L <map> <set>
__cpp_lib_generic_unordered_lookup 201811L <unordered_map> <unordered_set>
__cpp_lib_hardware_interference_size 201703L <new>
@ -509,6 +510,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_format_ranges 202207L
// # define __cpp_lib_formatters 202302L
# define __cpp_lib_forward_like 202207L
# define __cpp_lib_generator 202207L
# define __cpp_lib_invoke_r 202106L
# define __cpp_lib_ios_noreplace 202207L
# if __has_builtin(__builtin_is_implicit_lifetime)

View file

@ -51,9 +51,6 @@ module;
# if __has_include(<debugging>)
# error "please update the header information for <debugging> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<debugging>)
# if __has_include(<generator>)
# error "please update the header information for <generator> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<generator>)
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)

View file

@ -65,6 +65,7 @@ module;
#include <fstream>
#include <functional>
#include <future>
#include <generator>
#include <initializer_list>
#include <iomanip>
#include <ios>
@ -134,9 +135,6 @@ module;
# if __has_include(<debugging>)
# error "please update the header information for <debugging> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<debugging>)
# if __has_include(<generator>)
# error "please update the header information for <generator> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<generator>)
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)

View file

@ -8,7 +8,12 @@
//===----------------------------------------------------------------------===//
export namespace std {
#if 0
#if _LIBCPP_STD_VER >= 23
// [coro.generator], class template generator
using std::generator;
namespace pmr {
using std::pmr::generator;
}
#endif
} // namespace std

View file

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// Check that functions are marked [[nodiscard]]
#include <generator>
std::generator<int> generate_ints() {
co_yield 1;
co_yield 2;
co_yield 3;
}
void test() {
auto gen = generate_ints();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
gen.begin();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
gen.end();
}

View file

@ -480,6 +480,15 @@ future text_encoding
future tuple
future typeinfo
future version
generator compare
generator cstdint
generator cstring
generator initializer_list
generator limits
generator new
generator tuple
generator typeinfo
generator version
initializer_list version
iomanip cctype
iomanip cerrno

1 algorithm cctype
480 future tuple
481 future typeinfo
482 future version
483 generator compare
484 generator cstdint
485 generator cstring
486 generator initializer_list
487 generator limits
488 generator new
489 generator tuple
490 generator typeinfo
491 generator version
492 initializer_list version
493 iomanip cctype
494 iomanip cerrno

View file

@ -445,6 +445,15 @@ future string_view
future tuple
future typeinfo
future version
generator compare
generator cstdint
generator cstring
generator initializer_list
generator limits
generator new
generator tuple
generator typeinfo
generator version
initializer_list version
iomanip cctype
iomanip cerrno

1 algorithm cctype
445 future tuple
446 future typeinfo
447 future version
448 generator compare
449 generator cstdint
450 generator cstring
451 generator initializer_list
452 generator limits
453 generator new
454 generator tuple
455 generator typeinfo
456 generator version
457 initializer_list version
458 iomanip cctype
459 iomanip cerrno

View file

@ -0,0 +1,65 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// WARNING: This test was generated by generate_feature_test_macro_components.py
// and should not be edited manually.
// <generator>
// Test the feature test macros defined by <generator>
// clang-format off
#include <generator>
#include "test_macros.h"
#if TEST_STD_VER < 14
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
#elif TEST_STD_VER == 14
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
#elif TEST_STD_VER == 17
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
#elif TEST_STD_VER == 20
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
#elif TEST_STD_VER == 23
# ifndef __cpp_lib_generator
# error "__cpp_lib_generator should be defined in c++23"
# endif
# if __cpp_lib_generator != 202207L
# error "__cpp_lib_generator should have the value 202207L in c++23"
# endif
#elif TEST_STD_VER > 23
# ifndef __cpp_lib_generator
# error "__cpp_lib_generator should be defined in c++26"
# endif
# if __cpp_lib_generator != 202207L
# error "__cpp_lib_generator should have the value 202207L in c++26"
# endif
#endif // TEST_STD_VER > 23
// clang-format on

View file

@ -416,6 +416,10 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
# ifdef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should not be defined before c++14"
# endif
@ -1359,6 +1363,10 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
# ifndef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should be defined in c++14"
# endif
@ -2425,6 +2433,10 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
# ifndef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should be defined in c++17"
# endif
@ -3758,6 +3770,10 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif
# ifdef __cpp_lib_generator
# error "__cpp_lib_generator should not be defined before c++23"
# endif
# ifndef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should be defined in c++20"
# endif
@ -5286,6 +5302,13 @@
# error "__cpp_lib_generate_random should not be defined before c++26"
# endif
# ifndef __cpp_lib_generator
# error "__cpp_lib_generator should be defined in c++23"
# endif
# if __cpp_lib_generator != 202207L
# error "__cpp_lib_generator should have the value 202207L in c++23"
# endif
# ifndef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should be defined in c++23"
# endif
@ -7159,6 +7182,13 @@
# endif
# endif
# ifndef __cpp_lib_generator
# error "__cpp_lib_generator should be defined in c++26"
# endif
# if __cpp_lib_generator != 202207L
# error "__cpp_lib_generator should have the value 202207L in c++26"
# endif
# ifndef __cpp_lib_generic_associative_lookup
# error "__cpp_lib_generic_associative_lookup should be defined in c++26"
# endif

View file

@ -0,0 +1,123 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <generator>
// template<class Ref, class Val = void, class Allocator = void>
// class generator;
#include <generator>
#include <cassert>
#include <cstddef>
#include <memory>
#include <memory_resource>
#include <ranges>
#include <utility>
#include <vector>
template <class T>
class stateless_allocator {
public:
using value_type = T;
stateless_allocator() noexcept = default;
template <typename U>
constexpr stateless_allocator(const stateless_allocator<U>&) noexcept {}
[[nodiscard]] T* allocate(size_t n) { return static_cast<T*>(::operator new(n * sizeof(T))); }
void deallocate(void* p, size_t) noexcept { ::operator delete(p); }
template <class U>
constexpr bool operator==(const stateless_allocator<U>&) const noexcept {
return true;
}
};
template <class T>
class stateful_allocator {
public:
using value_type = T;
stateful_allocator() noexcept = default;
template <typename U>
constexpr stateful_allocator(const stateful_allocator<U>&) noexcept {}
[[nodiscard]] T* allocate(size_t n) { return static_cast<T*>(::operator new(n * sizeof(T))); }
void deallocate(void* p, size_t) noexcept { ::operator delete(p); }
template <class U>
constexpr bool operator==(const stateful_allocator<U>& other) const noexcept {
return state_ == other.state_;
}
private:
int state_ = 0;
};
template <class Allocator>
bool test_with_allocator() {
std::vector<int> expected_fib_vec = {0, 1, 1, 2, 3};
{
auto fib = []() -> std::generator<int, int, Allocator> {
int a = 0;
int b = 1;
while (true) {
co_yield std::exchange(a, std::exchange(b, a + b));
}
};
assert((fib() | std::views::take(5) | std::ranges::to<std::vector>()) == expected_fib_vec);
}
{
auto fib = [](std::allocator_arg_t, Allocator) -> std::generator<int, int, Allocator> {
int a = 0;
int b = 1;
while (true) {
co_yield std::exchange(a, std::exchange(b, a + b));
}
};
assert((fib(std::allocator_arg, {}) | std::views::take(5) | std::ranges::to<std::vector>()) == expected_fib_vec);
}
{
auto fib = [](std::allocator_arg_t, Allocator) -> std::generator<int> {
int a = 0;
int b = 1;
while (true) {
co_yield std::exchange(a, std::exchange(b, a + b));
}
};
assert((fib(std::allocator_arg, {}) | std::views::take(5) | std::ranges::to<std::vector>()) == expected_fib_vec);
}
return true;
}
bool test() {
test_with_allocator<std::allocator<std::byte>>();
test_with_allocator<stateless_allocator<std::byte>>();
test_with_allocator<stateful_allocator<std::byte>>();
test_with_allocator<std::pmr::polymorphic_allocator<std::byte>>();
test_with_allocator<std::allocator<float>>();
test_with_allocator<stateless_allocator<float>>();
test_with_allocator<stateful_allocator<float>>();
test_with_allocator<std::pmr::polymorphic_allocator<float>>();
return true;
};
int main() {
test();
return 0;
}

View file

@ -0,0 +1,48 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <generator>
// template<class Ref, class Val = void, class Allocator = void>
// class generator;
#include <generator>
#include <cassert>
#include <concepts>
#include <ranges>
template <class G, class V, class R, class RR>
constexpr bool conformance() {
static_assert(std::ranges::range<G>);
static_assert(std::ranges::view<G>);
static_assert(std::ranges::input_range<G>);
static_assert(!std::ranges::forward_range<G>);
static_assert(!std::ranges::borrowed_range<G>);
static_assert(std::same_as<std::ranges::range_value_t<G>, V>);
static_assert(std::same_as<std::ranges::range_reference_t<G>, R>);
static_assert(std::same_as<std::ranges::range_rvalue_reference_t<G>, RR>);
return true;
}
static_assert(conformance<std::generator<int>, int, int&&, int&&>());
static_assert(conformance<std::generator<int, int>, int, int, int>());
static_assert(conformance<std::generator<int&>, int, int&, int&&>());
static_assert(conformance<std::generator<int&, int>, int, int&, int&&>());
static_assert(conformance<std::generator<const int&>, int, const int&, const int&&>());
static_assert(conformance<std::generator<const int&, int>, int, const int&, const int&&>());
static_assert(conformance<std::generator<int&&>, int, int&&, int&&>());
static_assert(conformance<std::generator<int&&, int>, int, int&&, int&&>());
static_assert(conformance<std::generator<const int&&>, int, const int&&, const int&&>());
static_assert(conformance<std::generator<const int&&, int>, int, const int&&, const int&&>());

View file

@ -0,0 +1,56 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <generator>
// template<class Ref, class Val = void, class Allocator = void>
// class generator;
#include <generator>
#include <cassert>
#include <ranges>
#include <utility>
#include <vector>
std::generator<int> fib() {
int a = 0;
int b = 1;
while (true) {
co_yield std::exchange(a, std::exchange(b, a + b));
}
}
std::generator<const int&> range_fib() {
co_yield std::ranges::elements_of(std::vector<int>{0, 1});
co_yield std::ranges::elements_of(std::vector<int>{1, 2});
co_yield std::ranges::elements_of(std::vector<int>{3, 5});
co_yield std::ranges::elements_of(std::vector<int>{5, 8});
}
bool test() {
{
std::vector<int> expected_fib_vec = {0, 1, 1, 2, 3};
{
auto fib_vec = fib() | std::views::take(5) | std::ranges::to<std::vector<int>>();
assert(fib_vec == expected_fib_vec);
}
{
auto fib_vec = range_fib() | std::views::take(5) | std::ranges::to<std::vector<int>>();
assert(fib_vec == expected_fib_vec);
}
}
return true;
}
int main() {
test();
return 0;
}

View file

@ -0,0 +1,97 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++23
// <generator>
// template<class Ref, class Val = void, class Allocator = void>
// class generator;
#include <generator>
#include <cassert>
#include <numeric>
#include <ranges>
#include <utility>
#include <vector>
std::generator<int> fib() {
int a = 0;
int b = 1;
while (true) {
co_yield std::exchange(a, std::exchange(b, a + b));
}
}
std::generator<int> recursive_fib(int depth) {
if (depth == 0) {
co_yield std::ranges::elements_of(fib());
} else {
co_yield std::ranges::elements_of(recursive_fib(depth - 1));
}
};
struct tree_node {
tree_node* left;
tree_node* right;
int element;
~tree_node() {
delete left;
delete right;
}
};
tree_node* build_tree(int depth) {
if (depth == 0) {
return nullptr;
}
tree_node* root = new tree_node();
root->element = depth;
root->left = build_tree(depth - 1);
root->right = build_tree(depth - 1);
return root;
}
std::generator<int> traversal(tree_node* node) {
if (node == nullptr) {
co_return;
}
co_yield std::ranges::elements_of(traversal(node->left));
co_yield node->element;
co_yield std::ranges::elements_of(traversal(node->right));
}
bool test() {
{
std::vector<int> expected_fib_vec = {0, 1, 1, 2, 3};
{
auto fib_vec = recursive_fib(1) | std::views::take(5) | std::ranges::to<std::vector<int>>();
assert(fib_vec == expected_fib_vec);
}
{
auto fib_vec = recursive_fib(42) | std::views::take(5) | std::ranges::to<std::vector<int>>();
assert(fib_vec == expected_fib_vec);
}
}
{
tree_node* tree_root = build_tree(10);
auto node_vec = traversal(tree_root) | std::ranges::to<std::vector<int>>();
assert(node_vec.size() == 1023);
assert(std::reduce(node_vec.cbegin(), node_vec.cend()) == 2036);
delete tree_root;
}
return true;
}
int main() {
test();
return 0;
}

View file

@ -722,6 +722,13 @@ feature_test_macros = [
"headers": ["random"],
"unimplemented": True,
},
{
"name": "__cpp_lib_generator",
"values": {
"c++23": 202207
}, # P2502R2: std::generator: Synchronous Coroutine Generator for Ranges
"headers": ["generator"],
},
{
"name": "__cpp_lib_generic_associative_lookup",
"values": {"c++14": 201304},

View file

@ -164,7 +164,6 @@ module_c_headers = [h for h in all_headers if h.has_cxx20_module() and h.is_cstd
# modules will fail to build if a header is added but this list is not updated.
headers_not_available = list(map(Header, [
"debugging",
"generator",
"hazard_pointer",
"inplace_vector",
"linalg",