@@ -52,6 +52,9 @@ inline constexpr bool isOptionalV = false;
5252
5353template <typename T>
5454inline constexpr bool isOptionalV<Optional<T>> = true ;
55+
56+ template <typename T>
57+ inline constexpr bool isOptionalV<Optional<T&>> = true ;
5558}
5659
5760/* * A compact optional that automatically uses nullable_traits<T> when
@@ -632,6 +635,298 @@ concept isDerivedFromOptional = requires(T const& t) {
632635
633636} // namespace detail
634637
638+
639+ namespace detail {
640+ #if defined(__cpp_lib_reference_from_temporary)
641+ using std::reference_constructs_from_temporary_v;
642+ using std::reference_converts_from_temporary_v;
643+ #else
644+ template <class To , class From >
645+ concept reference_converts_from_temporary_v =
646+ std::is_reference_v<To> &&
647+ (
648+ (!std::is_reference_v<From> &&
649+ std::is_convertible_v<std::remove_cvref_t <From>*,
650+ std::remove_cvref_t <To>*>)
651+ ||
652+ (std::is_lvalue_reference_v<To> &&
653+ std::is_const_v<std::remove_reference_t <To>> &&
654+ std::is_convertible_v<From, const std::remove_cvref_t <To>&&> &&
655+ !std::is_convertible_v<From, std::remove_cvref_t <To>&>)
656+ );
657+
658+ template <class To , class From >
659+ inline constexpr bool reference_constructs_from_temporary_v
660+ = reference_converts_from_temporary_v<To, From>;
661+ #endif
662+ } // detail
663+
664+ template <class T >
665+ class Optional <T&> {
666+ T* p_ = nullptr ;
667+
668+ template <class U >
669+ static constexpr bool ok_bind_v
670+ = std::is_constructible_v<T&, U>
671+ && !detail::reference_constructs_from_temporary_v<T&, U>;
672+
673+ public:
674+ using value_type = T;
675+
676+ constexpr
677+ Optional () noexcept = default ;
678+
679+ constexpr
680+ Optional (Optional const &) noexcept = default ;
681+
682+ constexpr
683+ Optional (Optional&&) noexcept = default ;
684+
685+ constexpr
686+ Optional (std::nullopt_t ) noexcept
687+ : Optional() {}
688+
689+ template <class U >
690+ requires (
691+ !std::is_same_v<std::remove_cvref_t <U>, Optional> &&
692+ !std::is_same_v<std::remove_cvref_t <U>, std::in_place_t > &&
693+ ok_bind_v<U>)
694+ constexpr
695+ explicit (!std::is_convertible_v<U, T&>)
696+ Optional (U&& u)
697+ noexcept (std::is_nothrow_constructible_v<T&, U>)
698+ {
699+ T& r (static_cast <U&&>(u));
700+ p_ = std::addressof (r);
701+ }
702+
703+ template <class U >
704+ requires ok_bind_v<U&>
705+ constexpr
706+ explicit (!std::is_convertible_v<U&, T&>)
707+ Optional (Optional<U>& rhs)
708+ noexcept (std::is_nothrow_constructible_v<T&, U&>)
709+ {
710+ if (rhs)
711+ {
712+ p_ = std::addressof (*rhs);
713+ }
714+ }
715+
716+ template <class U >
717+ requires ok_bind_v<U const &>
718+ constexpr
719+ explicit (!std::is_convertible_v<U const &, T&>)
720+ Optional (Optional<U> const & rhs)
721+ noexcept (std::is_nothrow_constructible_v<T&, U const &>)
722+ {
723+ if (rhs)
724+ {
725+ p_ = std::addressof (*rhs);
726+ }
727+ }
728+
729+ template <class U >
730+ requires ok_bind_v<U&>
731+ constexpr
732+ Optional (std::optional<U>& o)
733+ noexcept (std::is_nothrow_constructible_v<T&, U&>)
734+ {
735+ if (o)
736+ {
737+ p_ = std::addressof (*o);
738+ }
739+ }
740+
741+ template <class U >
742+ requires ok_bind_v<U const &>
743+ constexpr
744+ Optional (std::optional<U> const & o)
745+ noexcept (std::is_nothrow_constructible_v<T&, U const &>)
746+ {
747+ if (o)
748+ {
749+ p_ = std::addressof (*o);
750+ }
751+ }
752+
753+ constexpr Optional&
754+ operator =(Optional const &) noexcept = default ;
755+
756+ constexpr Optional&
757+ operator =(Optional&&) noexcept = default ;
758+
759+ constexpr Optional&
760+ operator =(std::nullopt_t ) noexcept
761+ {
762+ p_ = nullptr ;
763+ return *this ;
764+ }
765+
766+ template <class U >
767+ requires ok_bind_v<U>
768+ constexpr Optional&
769+ operator =(U&& u)
770+ noexcept (std::is_nothrow_constructible_v<T&, U>)
771+ {
772+ T& r (static_cast <U&&>(u));
773+ p_ = std::addressof (r);
774+ return *this ;
775+ }
776+
777+ template <class U >
778+ requires ok_bind_v<U&>
779+ constexpr
780+ Optional&
781+ operator =(Optional<U>& rhs)
782+ noexcept (std::is_nothrow_constructible_v<T&, U&>)
783+ {
784+ p_ = rhs ? std::addressof (*rhs) : nullptr ;
785+ return *this ;
786+ }
787+
788+ template <class U >
789+ requires ok_bind_v<U const &>
790+ constexpr
791+ Optional&
792+ operator =(Optional<U> const & rhs)
793+ noexcept (std::is_nothrow_constructible_v<T&, U const &>)
794+ {
795+ p_ = rhs ? std::addressof (*rhs) : nullptr ;
796+ return *this ;
797+ }
798+
799+ template <class U >
800+ requires ok_bind_v<U>
801+ constexpr
802+ Optional&
803+ operator =(Optional<U>&& rhs)
804+ noexcept (std::is_nothrow_constructible_v<T&, U>)
805+ {
806+ p_ = rhs ? std::addressof (*rhs) : nullptr ;
807+ return *this ;
808+ }
809+
810+ template <class U >
811+ requires ok_bind_v<U>
812+ constexpr
813+ value_type&
814+ emplace (U&& u)
815+ noexcept (std::is_nothrow_constructible_v<T&, U>)
816+ {
817+ T& r (static_cast <U&&>(u));
818+ p_ = std::addressof (r);
819+ return *p_;
820+ }
821+
822+ static
823+ constexpr
824+ bool
825+ is_inlined () noexcept
826+ {
827+ return true ;
828+ }
829+
830+ constexpr
831+ bool
832+ has_value () const noexcept
833+ {
834+ return p_ != nullptr ;
835+ }
836+
837+ constexpr
838+ explicit
839+ operator bool () const noexcept
840+ {
841+ return has_value ();
842+ }
843+
844+ constexpr
845+ void
846+ reset () noexcept
847+ {
848+ p_ = nullptr ;
849+ }
850+
851+ constexpr
852+ value_type*
853+ operator ->() noexcept
854+ {
855+ MRDOCS_ASSERT (has_value ());
856+ return p_;
857+ }
858+
859+ constexpr
860+ value_type const *
861+ operator ->() const noexcept
862+ {
863+ MRDOCS_ASSERT (has_value ());
864+ return p_;
865+ }
866+
867+ constexpr
868+ value_type&
869+ operator *() noexcept
870+ {
871+ MRDOCS_ASSERT (has_value ());
872+ return *p_;
873+ }
874+
875+ constexpr
876+ value_type const &
877+ operator *() const noexcept
878+ {
879+ MRDOCS_ASSERT (has_value ());
880+ return *p_;
881+ }
882+
883+ constexpr
884+ value_type&
885+ value () & noexcept
886+ {
887+ MRDOCS_ASSERT (has_value ());
888+ return *p_;
889+ }
890+
891+ constexpr
892+ value_type const &
893+ value () const & noexcept
894+ {
895+ MRDOCS_ASSERT (has_value ());
896+ return *p_;
897+ }
898+
899+ constexpr
900+ value_type&
901+ value () && noexcept
902+ {
903+ MRDOCS_ASSERT (has_value ());
904+ return *p_;
905+ }
906+
907+ constexpr
908+ value_type const &
909+ value () const && noexcept
910+ {
911+ MRDOCS_ASSERT (has_value ());
912+ return *p_;
913+ }
914+
915+ constexpr void
916+ swap (Optional& other) noexcept
917+ {
918+ using std::swap;
919+ swap (p_, other.p_ );
920+ }
921+ };
922+
923+ template <class T >
924+ constexpr void
925+ swap (Optional<T&>& a, Optional<T&>& b) noexcept
926+ {
927+ a.swap (b);
928+ }
929+
635930/* * Compares two Optional values for equality.
636931 Returns true if both are engaged and their contained values are equal, or both are disengaged.
637932 @return `true` if both optionals are engaged and equal, or both are disengaged; otherwise, `false`.
@@ -893,6 +1188,7 @@ operator<=>(Optional<T> const& x, U const& v)
8931188{
8941189 return bool (x) ? *x <=> v : std::strong_ordering::less;
8951190}
1191+
8961192} // namespace clang::mrdocs
8971193
8981194#endif
0 commit comments