@@ -135,7 +135,7 @@ namespace STDEXEC {
135135 if (!__has_value_) {
136136 STDEXEC_THROW (__bad_optional_access ());
137137 }
138- return static_cast <_Tp&&>(__value_);
138+ return static_cast <_Tp&&>(static_cast <_Tp&>( __value_) );
139139 }
140140
141141 constexpr auto operator *() & noexcept -> _Tp& {
@@ -150,17 +150,17 @@ namespace STDEXEC {
150150
151151 constexpr auto operator *() && noexcept -> _Tp&& {
152152 STDEXEC_ASSERT (__has_value_);
153- return static_cast <_Tp&&>(__value_);
153+ return static_cast <_Tp&&>(static_cast <_Tp&>( __value_) );
154154 }
155155
156- constexpr auto operator ->() & noexcept -> _Tp* {
156+ constexpr auto operator ->() & noexcept -> std:: add_pointer_t < _Tp> {
157157 STDEXEC_ASSERT (__has_value_);
158- return & __value_;
158+ return std::addressof ( static_cast <_Tp&>( __value_)) ;
159159 }
160160
161- constexpr auto operator ->() const & noexcept -> const _Tp* {
161+ constexpr auto operator ->() const & noexcept -> std:: add_pointer_t < const _Tp> {
162162 STDEXEC_ASSERT (__has_value_);
163- return & __value_;
163+ return std::addressof ( static_cast < const _Tp&>( __value_)) ;
164164 }
165165
166166 [[nodiscard]]
@@ -175,6 +175,71 @@ namespace STDEXEC {
175175 }
176176 }
177177 };
178+
179+ // __optional<T&>
180+ template <class _Tp >
181+ struct __optional <_Tp&> {
182+ _Tp* __value_ = nullptr ;
183+
184+ __optional () noexcept = default ;
185+
186+ __optional (__nullopt_t ) noexcept {
187+ }
188+
189+ template <__not_decays_to<__optional> _Up>
190+ requires __std::constructible_from<_Tp&, _Up>
191+ constexpr __optional (_Up&& __val) noexcept (__nothrow_constructible_from<_Tp&, _Up>) {
192+ emplace (static_cast <_Up&&>(__val));
193+ }
194+
195+ template <__not_decays_to<__optional> _Up>
196+ requires __std::constructible_from<_Tp&, _Up>
197+ constexpr __optional (std::in_place_t , _Up&& __val)
198+ noexcept (__nothrow_constructible_from<_Tp&, _Up>) {
199+ emplace (static_cast <_Up&&>(__val));
200+ }
201+
202+ template <class _Up >
203+ requires __std::constructible_from<_Tp&, _Up>
204+ constexpr auto emplace (_Up&& __us) noexcept (__nothrow_constructible_from<_Tp&, _Up>) -> _Tp& {
205+ __value_ = std::addressof (static_cast <_Up&&>(__us));
206+ return *__value_;
207+ }
208+
209+ template <class _Fn , class ... _Args>
210+ requires __std::same_as<_Tp&, __call_result_t <_Fn, _Args...>>
211+ auto __emplace_from (_Fn&& __f, _Args&&... __args) noexcept (__nothrow_callable<_Fn, _Args...>)
212+ -> _Tp& {
213+ __value_ = std::addressof (static_cast <_Fn&&>(__f)(static_cast <_Args&&>(__args)...));
214+ return *__value_;
215+ }
216+
217+ constexpr auto value () const -> _Tp& {
218+ if (__value_ == nullptr ) {
219+ STDEXEC_THROW (__bad_optional_access ());
220+ }
221+ return *__value_;
222+ }
223+
224+ constexpr auto operator *() const -> _Tp& {
225+ STDEXEC_ASSERT (__value_ != nullptr );
226+ return *__value_;
227+ }
228+
229+ constexpr auto operator ->() const -> _Tp* {
230+ STDEXEC_ASSERT (__value_ != nullptr );
231+ return __value_;
232+ }
233+
234+ [[nodiscard]]
235+ constexpr auto has_value () const noexcept -> bool {
236+ return __value_ != nullptr ;
237+ }
238+
239+ constexpr void reset () noexcept {
240+ __value_ = nullptr ;
241+ }
242+ };
178243 } // namespace __opt
179244
180245 using __opt::__optional;
0 commit comments