@@ -276,19 +276,29 @@ class optional {
276276
277277 template <class U >
278278 constexpr explicit (!std::is_convertible_v<U, T>) optional(const optional<U>& rhs)
279- requires detail::enable_from_other<T, U, const U&> && std::is_convertible_v<const U&, T>;
279+ requires(!std::is_reference_v<U> && detail::enable_from_other<T, U, const U&> &&
280+ std::is_convertible_v<const U&, T>);
280281
281282 template <class U >
282283 constexpr explicit (!std::is_convertible_v<U, T>) optional(const optional<U>& rhs)
283- requires detail::enable_from_other<T, U, const U&> && (!std::is_convertible_v<const U&, T>);
284+ requires(!std::is_reference_v<U> && detail::enable_from_other<T, U, const U&> &&
285+ !std::is_convertible_v<const U&, T>);
284286
285287 template <class U >
286288 constexpr explicit (!std::is_convertible_v<U, T>) optional(optional<U>&& rhs)
287- requires detail::enable_from_other<T, U, U&&> && std::is_convertible_v<U&&, T>;
289+ requires(!std::is_reference_v<U> && detail::enable_from_other<T, U, U &&> && std::is_convertible_v<U &&, T>) ;
288290
289291 template <class U >
290292 constexpr explicit (!std::is_convertible_v<U, T>) optional(optional<U>&& rhs)
291- requires detail::enable_from_other<T, U, U&&> && (!std::is_convertible_v<U &&, T>);
293+ requires(!std::is_reference_v<U> && detail::enable_from_other<T, U, U &&> && !std::is_convertible_v<U &&, T>);
294+
295+ template <class U >
296+ constexpr explicit (!std::is_convertible_v<U&, T>) optional(const optional<U&>& rhs)
297+ requires(detail::enable_from_other<T, U&, U&> && std::is_convertible_v<U&, T>);
298+
299+ template <class U >
300+ constexpr explicit (!std::is_convertible_v<U&, T>) optional(const optional<U&>& rhs)
301+ requires(detail::enable_from_other<T, U&, U&> && !std::is_convertible_v<U&, T>);
292302
293303 // \ref{optional.dtor}, destructor
294304 constexpr ~optional ()
@@ -325,11 +335,15 @@ class optional {
325335
326336 template <class U >
327337 constexpr optional& operator =(const optional<U>& rhs)
328- requires detail::enable_assign_from_other<T, U, const U&>;
338+ requires (!std::is_reference_v<U> && detail::enable_assign_from_other<T, U, const U&>) ;
329339
330340 template <class U >
331341 constexpr optional& operator =(optional<U>&& rhs)
332- requires detail::enable_assign_from_other<T, U, U>;
342+ requires (!std::is_reference_v<U> && detail::enable_assign_from_other<T, U, U>);
343+
344+ template <class U >
345+ constexpr optional& operator =(const optional<U&>& rhs)
346+ requires (detail::enable_assign_from_other<T, U&, U&>);
333347
334348 template <class ... Args>
335349 constexpr T& emplace (Args&&... args);
@@ -463,7 +477,8 @@ inline constexpr optional<T>::optional(U&& u)
463477template <class T >
464478template <class U >
465479inline constexpr optional<T>::optional(const optional<U>& rhs)
466- requires detail::enable_from_other<T, U, const U&> && std::is_convertible_v<const U&, T>
480+ requires (!std::is_reference_v<U> && detail::enable_from_other<T, U, const U&> &&
481+ std::is_convertible_v<const U&, T>)
467482{
468483 if (rhs.has_value ()) {
469484 construct (*rhs);
@@ -473,7 +488,8 @@ inline constexpr optional<T>::optional(const optional<U>& rhs)
473488template <class T >
474489template <class U >
475490inline constexpr optional<T>::optional(const optional<U>& rhs)
476- requires detail::enable_from_other<T, U, const U&> && (!std::is_convertible_v<const U&, T>)
491+ requires (!std::is_reference_v<U> && detail::enable_from_other<T, U, const U&> &&
492+ !std::is_convertible_v<const U&, T>)
477493{
478494 if (rhs.has_value ()) {
479495 construct (*rhs);
@@ -484,7 +500,7 @@ inline constexpr optional<T>::optional(const optional<U>& rhs)
484500template <class T >
485501template <class U >
486502inline constexpr optional<T>::optional(optional<U>&& rhs)
487- requires detail::enable_from_other<T, U, U&&> && std::is_convertible_v<U&&, T>
503+ requires (!std::is_reference_v<U> && detail::enable_from_other<T, U, U &&> && std::is_convertible_v<U &&, T>)
488504{
489505 if (rhs.has_value ()) {
490506 construct (std::move (*rhs));
@@ -494,13 +510,33 @@ inline constexpr optional<T>::optional(optional<U>&& rhs)
494510template <class T >
495511template <class U >
496512inline constexpr optional<T>::optional(optional<U>&& rhs)
497- requires detail::enable_from_other<T, U, U&&> && ( !std::is_convertible_v<U &&, T>)
513+ requires (!std::is_reference_v<U> && detail::enable_from_other<T, U, U &&> && !std::is_convertible_v<U &&, T>)
498514{
499515 if (rhs.has_value ()) {
500516 construct (std::move (*rhs));
501517 }
502518}
503519
520+ template <class T >
521+ template <class U >
522+ inline constexpr optional<T>::optional(const optional<U&>& rhs)
523+ requires (detail::enable_from_other<T, U&, U&> && std::is_convertible_v<U&, T>)
524+ {
525+ if (rhs.has_value ()) {
526+ construct (*rhs);
527+ }
528+ }
529+
530+ template <class T >
531+ template <class U >
532+ inline constexpr optional<T>::optional(const optional<U&>& rhs)
533+ requires (detail::enable_from_other<T, U&, U&> && !std::is_convertible_v<U&, T>)
534+ {
535+ if (rhs.has_value ()) {
536+ construct (*rhs);
537+ }
538+ }
539+
504540// 22.5.3.3 Destructor[optional.dtor]
505541
506542template <class T >
@@ -571,7 +607,7 @@ inline constexpr optional<T>& optional<T>::operator=(U&& u)
571607template <class T >
572608template <class U >
573609inline constexpr optional<T>& optional<T>::operator =(const optional<U>& rhs)
574- requires detail::enable_assign_from_other<T, U, const U&>
610+ requires (!std::is_reference_v<U> && detail::enable_assign_from_other<T, U, const U&>)
575611{
576612 if (has_value ()) {
577613 if (rhs.has_value ()) {
@@ -595,7 +631,7 @@ inline constexpr optional<T>& optional<T>::operator=(const optional<U>& rhs)
595631template <class T >
596632template <class U >
597633inline constexpr optional<T>& optional<T>::operator =(optional<U>&& rhs)
598- requires detail::enable_assign_from_other<T, U, U>
634+ requires (!std::is_reference_v<U> && detail::enable_assign_from_other<T, U, U>)
599635{
600636 if (has_value ()) {
601637 if (rhs.has_value ()) {
@@ -612,6 +648,26 @@ inline constexpr optional<T>& optional<T>::operator=(optional<U>&& rhs)
612648 return *this ;
613649}
614650
651+ template <class T >
652+ template <class U >
653+ inline constexpr optional<T>& optional<T>::operator =(const optional<U&>& rhs)
654+ requires (detail::enable_assign_from_other<T, U&, U&>)
655+ {
656+ if (has_value ()) {
657+ if (rhs.has_value ()) {
658+ value_ = *rhs;
659+ } else {
660+ hard_reset ();
661+ }
662+ }
663+
664+ else if (rhs.has_value ()) {
665+ construct (*rhs);
666+ }
667+
668+ return *this ;
669+ }
670+
615671// / Constructs the value in-place, destroying the current one if there is
616672// / one.
617673template <class T >
0 commit comments