2222#error <experimental/generator> requires /std:c++latest or /await compiler options
2323#endif // ^^^ no coroutine support ^^^
2424
25-
2625#pragma pack(push, _CRT_PACKING)
2726#pragma warning(push, _STL_WARNING_LEVEL)
2827#pragma warning(disable : _STL_DISABLED_WARNINGS)
@@ -33,18 +32,16 @@ _STL_DISABLE_CLANG_WARNINGS
3332_STD_BEGIN
3433
3534namespace experimental {
36-
37- template <typename _Ty, typename _Alloc = allocator<char>>
35+ // NOTE WELL: _CPPUNWIND currently affects the ABI of generator.
36+ template <class _Ty, class _Alloc = allocator<char>>
3837 struct generator {
3938 struct promise_type {
40- _Ty const* _CurrentValue;
41- #if 1 // TRANSITION, VSO-1172852
42- #ifdef _CPPUNWIND
43- exception_ptr _Eptr;
44- #endif // _CPPUNWIND
39+ const _Ty* _Value;
40+ #ifdef _CPPUNWIND // TRANSITION, VSO-1172852
41+ exception_ptr _Exception;
4542#endif // TRANSITION, VSO-1172852
4643
47- auto get_return_object() {
44+ generator get_return_object() noexcept {
4845 return generator{*this};
4946 }
5047
@@ -56,38 +53,38 @@ namespace experimental {
5653 return {};
5754 }
5855
59- #if defined(_CPPUNWIND) || defined(__cpp_impl_coroutine)
60- void unhandled_exception() noexcept {
61- #if 1 // TRANSITION, VSO-1172852
56+ #ifndef _KERNEL_MODE
6257#ifdef _CPPUNWIND
63- _Eptr = _STD current_exception();
64- #else // ^^^ _CPPUNWIND / !_CPPUNWIND vvv
65- abort ();
66- #endif // _CPPUNWIND
58+ #if 1 // TRANSITION, VSO-1172852
59+ void unhandled_exception() noexcept {
60+ _Exception = _STD current_exception ();
61+ }
6762#else // ^^^ workaround / no workaround vvv
63+ void unhandled_exception() {
6864 throw;
69- #endif // TRANSITION, VSO-1172852
7065 }
71- #endif // defined(_CPPUNWIND) || defined(__cpp_impl_coroutine)
66+ #endif // TRANSITION, VSO-1172852
67+ #else // ^^^ defined(_CPPUNWIND) / !defined(_CPPUNWIND) vvv
68+ void unhandled_exception() noexcept {}
69+ #endif // _CPPUNWIND
70+ #endif // _KERNEL_MODE
7271
73- #if 1 // TRANSITION, VSO-1172852
72+ #ifdef _CPPUNWIND // TRANSITION, VSO-1172852
7473 void _Rethrow_if_exception() {
75- #ifdef _CPPUNWIND
76- if (_Eptr) {
77- _STD rethrow_exception(_Eptr);
74+ if (_Exception) {
75+ _STD rethrow_exception(_Exception);
7876 }
79- #endif // _CPPUNWIND
8077 }
8178#endif // TRANSITION, VSO-1172852
8279
83- auto yield_value(_Ty const& _Value) {
84- _CurrentValue = _STD addressof(_Value );
85- return suspend_always {};
80+ suspend_always yield_value(const _Ty& _Val) noexcept {
81+ _Value = _STD addressof(_Val );
82+ return {};
8683 }
8784
88- void return_void() {}
85+ void return_void() noexcept {}
8986
90- template <typename _Uty>
87+ template <class _Uty>
9188 _Uty&& await_transform(_Uty&& _Whatever) {
9289 static_assert(_Always_false<_Uty>,
9390 "co_await is not supported in coroutines of type std::experimental::generator");
@@ -98,15 +95,16 @@ namespace experimental {
9895 static_assert(is_same_v<char*, typename allocator_traits<_Alloc_char>::pointer>,
9996 "generator does not support allocators with fancy pointer types");
10097 static_assert(
101- allocator_traits<_Alloc_char>::is_always_equal::value, "generator only supports stateless allocators");
98+ allocator_traits<_Alloc_char>::is_always_equal::value && is_default_constructible_v<_Alloc_char>,
99+ "generator supports only stateless allocators");
102100
103101 static void* operator new(size_t _Size) {
104- _Alloc_char _Al;
102+ _Alloc_char _Al{} ;
105103 return allocator_traits<_Alloc_char>::allocate(_Al, _Size);
106104 }
107105
108106 static void operator delete(void* _Ptr, size_t _Size) noexcept {
109- _Alloc_char _Al;
107+ _Alloc_char _Al{} ;
110108 return allocator_traits<_Alloc_char>::deallocate(_Al, static_cast<char*>(_Ptr), _Size);
111109 }
112110 };
@@ -115,21 +113,19 @@ namespace experimental {
115113 using iterator_category = input_iterator_tag;
116114 using difference_type = ptrdiff_t;
117115 using value_type = _Ty;
118- using reference = _Ty const&;
119- using pointer = _Ty const*;
116+ using reference = const _Ty &;
117+ using pointer = const _Ty *;
120118
121119 coroutine_handle<promise_type> _Coro = nullptr;
122120
123121 iterator() = default;
124- iterator(nullptr_t) : _Coro(nullptr) {}
125-
126- iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg) {}
122+ explicit iterator(coroutine_handle<promise_type> _Coro_) noexcept : _Coro(_Coro_) {}
127123
128124 iterator& operator++() {
129125 _Coro.resume();
130126 if (_Coro.done()) {
131- #if 1 // TRANSITION, VSO-1172852
132- _STD exchange(_Coro, {} ).promise()._Rethrow_if_exception();
127+ #ifdef _CPPUNWIND // TRANSITION, VSO-1172852
128+ _STD exchange(_Coro, nullptr ).promise()._Rethrow_if_exception();
133129#else // ^^^ workaround / no workaround vvv
134130 _Coro = nullptr;
135131#endif // TRANSITION, VSO-1172852
@@ -139,61 +135,54 @@ namespace experimental {
139135 }
140136
141137 void operator++(int) {
142- // This postincrement operator meets the requirements of the Ranges TS
143- // InputIterator concept, but not those of Standard C++ InputIterator .
138+ // This operator meets the requirements of the C++20 input_iterator concept,
139+ // but not the Cpp17InputIterator requirements .
144140 ++*this;
145141 }
146142
147- _NODISCARD bool operator==(iterator const& _Right) const {
143+ _NODISCARD bool operator==(const iterator & _Right) const noexcept {
148144 return _Coro == _Right._Coro;
149145 }
150146
151- _NODISCARD bool operator!=(iterator const& _Right) const {
147+ _NODISCARD bool operator!=(const iterator & _Right) const noexcept {
152148 return !(*this == _Right);
153149 }
154150
155- _NODISCARD reference operator*() const {
156- return *_Coro.promise()._CurrentValue ;
151+ _NODISCARD reference operator*() const noexcept {
152+ return *_Coro.promise()._Value ;
157153 }
158154
159- _NODISCARD pointer operator->() const {
160- return _Coro.promise()._CurrentValue ;
155+ _NODISCARD pointer operator->() const noexcept {
156+ return _Coro.promise()._Value ;
161157 }
162158 };
163159
164160 _NODISCARD iterator begin() {
165161 if (_Coro) {
166162 _Coro.resume();
167163 if (_Coro.done()) {
168- #if 1 // TRANSITION, VSO-1172852
164+ #ifdef _CPPUNWIND // TRANSITION, VSO-1172852
169165 _Coro.promise()._Rethrow_if_exception();
170166#endif // TRANSITION, VSO-1172852
171- return {nullptr };
167+ return {};
172168 }
173169 }
174170
175- return {_Coro};
171+ return iterator {_Coro};
176172 }
177173
178- _NODISCARD iterator end() {
179- return {nullptr };
174+ _NODISCARD iterator end() noexcept {
175+ return {};
180176 }
181177
182- explicit generator(promise_type& _Prom) : _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) {}
178+ explicit generator(promise_type& _Prom) noexcept : _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) {}
183179
184- generator() = default;
185- generator(generator const&) = delete;
186- generator& operator=(generator const&) = delete;
180+ generator() = default;
187181
188- generator(generator&& _Right) : _Coro(_Right._Coro) {
189- _Right._Coro = nullptr;
190- }
182+ generator(generator&& _Right) noexcept : _Coro(_STD exchange(_Right._Coro, nullptr)) {}
191183
192- generator& operator=(generator&& _Right) {
193- if (this != _STD addressof(_Right)) {
194- _Coro = _Right._Coro;
195- _Right._Coro = nullptr;
196- }
184+ generator& operator=(generator&& _Right) noexcept {
185+ _Coro = _STD exchange(_Right._Coro, nullptr);
197186 return *this;
198187 }
199188
@@ -206,7 +195,6 @@ namespace experimental {
206195 private:
207196 coroutine_handle<promise_type> _Coro = nullptr;
208197 };
209-
210198} // namespace experimental
211199
212200_STD_END
0 commit comments