@@ -69,7 +69,7 @@ inline constexpr bool std::ranges::enable_view<beman::optional::optional<T>> = t
6969
7070// Iterators for optional<T&> have life times that are not tied to the optional.
7171template <class T >
72- inline constexpr bool std::ranges::enable_borrowed_range<beman::optional::optional<T>> = std::is_reference_v<T> ;
72+ inline constexpr bool std::ranges::enable_borrowed_range<beman::optional::optional<T& >> = true ;
7373
7474// Since P3168R2: Give std::optional Range Support.
7575#if defined(__cpp_lib_format_ranges)
@@ -699,21 +699,15 @@ inline constexpr bool optional<T>::has_value() const noexcept {
699699// / bad_optional_access
700700template <class T >
701701inline constexpr T& optional<T>::value() & {
702- if (has_value ())
703- return value_;
704- throw bad_optional_access ();
702+ return has_value () ? value_ : throw bad_optional_access ();
705703}
706704template <class T >
707705inline constexpr const T& optional<T>::value() const & {
708- if (has_value ())
709- return value_;
710- throw bad_optional_access ();
706+ return has_value () ? value_ : throw bad_optional_access ();
711707}
712708template <class T >
713709inline constexpr T&& optional<T>::value() && {
714- if (has_value ())
715- return std::move (value_);
716- throw bad_optional_access ();
710+ return has_value () ? std::move (value_) : throw bad_optional_access ();
717711}
718712
719713// / Returns the stored value if there is one, otherwise returns `u`
@@ -1090,8 +1084,8 @@ class optional<T&> {
10901084 public:
10911085 // \ref{optionalref.ctor}, constructors
10921086
1093- constexpr optional () noexcept ;
1094- constexpr optional (nullopt_t ) noexcept ;
1087+ constexpr optional () noexcept = default ;
1088+ constexpr optional (nullopt_t ) noexcept : optional() {}
10951089 constexpr optional (const optional& rhs) noexcept = default;
10961090
10971091 template <class Arg >
@@ -1102,12 +1096,9 @@ class optional<T&> {
11021096 requires (std::is_constructible_v<T&, U> && !(std::is_same_v<std::remove_cvref_t <U>, in_place_t >) &&
11031097 !(std::is_same_v<std::remove_cvref_t <U>, optional>) &&
11041098 !detail::reference_constructs_from_temporary_v<T&, U>)
1105- constexpr explicit (!std::is_convertible_v<U, T&>) optional(U&& u) noexcept (
1106- std::is_nothrow_constructible_v<T&, U>) { // Creates a variable, \tcode{r}, as if by \tcode{T\&
1107- // r(std::forward<Arg>(arg));} and then initializes \exposid{val}
1108- // with \tcode{addressof(r)}
1109- T& r (std::forward<U>(u));
1110- value_ = std::addressof (r);
1099+ constexpr explicit (!std::is_convertible_v<U, T&>)
1100+ optional(U&& u) noexcept (std::is_nothrow_constructible_v<T&, U>) {
1101+ convert_ref_init_val (u);
11111102 }
11121103
11131104 template <class U >
@@ -1189,39 +1180,40 @@ class optional<T&> {
11891180 constexpr explicit operator bool () const noexcept ;
11901181 constexpr bool has_value () const noexcept ;
11911182 constexpr T& value () const ;
1192- template <class U >
1183+ template <class U = std:: remove_cv_t <T> >
11931184 constexpr std::remove_cv_t <T> value_or (U&& u) const ;
11941185
11951186 // \ref{optionalref.monadic}, monadic operations
11961187 template <class F >
11971188 constexpr auto and_then (F&& f) const ;
11981189 template <class F >
1199- constexpr auto transform (F&& f) const -> optional<std::invoke_result_t<F, T&>>;
1190+ constexpr optional<std::invoke_result_t <F, T&>> transform (F&& f) const ;
12001191 template <class F >
12011192 constexpr optional or_else (F&& f) const ;
12021193
12031194 // \ref{optional.mod}, modifiers
12041195 constexpr void reset () noexcept ;
12051196
12061197 private:
1207- T* value_; // exposition only
1198+ T* value_ = nullptr ; // exposition only
1199+
1200+ // \ref{optionalref.expos}, exposition only helper functions
1201+ template <class U >
1202+ constexpr void convert_ref_init_val (U&& u) {
1203+ // Creates a variable, \tcode{r},
1204+ // as if by \tcode{T\& r(std::forward<U>(u));}
1205+ // and then initializes \exposid{val} with \tcode{addressof(r)}
1206+ T& r (std::forward<U>(u));
1207+ value_ = std::addressof (r);
1208+ }
12081209};
12091210
12101211// \rSec3[optionalref.ctor]{Constructors}
1211- template <class T >
1212- constexpr optional<T&>::optional() noexcept : value_(nullptr ) {}
1213-
1214- template <class T >
1215- constexpr optional<T&>::optional(nullopt_t ) noexcept : value_(nullptr ) {}
1216-
12171212template <class T >
12181213template <class Arg >
12191214 requires (std::is_constructible_v<T&, Arg> && !detail::reference_constructs_from_temporary_v<T&, Arg>)
1220- constexpr optional<T&>::optional(
1221- in_place_t , Arg&& arg) { // Creates a variable, \tcode{r}, as if by \tcode{T\& r(std::forward<Arg>(arg));} and
1222- // then initializes \exposid{val} with \tcode{addressof(r)}
1223- T& r (std::forward<Arg>(arg));
1224- value_ = std::addressof (r);
1215+ constexpr optional<T&>::optional(in_place_t , Arg&& arg) {
1216+ convert_ref_init_val (std::forward<Arg>(arg));
12251217}
12261218
12271219// Clang is unhappy with the out-of-line definition
@@ -1239,9 +1231,7 @@ template <class U>
12391231 !std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U&>)
12401232constexpr optional<T&>::optional(optional<U>& rhs) noexcept (std::is_nothrow_constructible_v<T&, U&>) {
12411233 if (rhs.has_value ()) {
1242- value_ = std::addressof (static_cast <T&>(*rhs));
1243- } else {
1244- value_ = nullptr ;
1234+ convert_ref_init_val (*rhs);
12451235 }
12461236}
12471237
@@ -1251,9 +1241,7 @@ template <class U>
12511241 !std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, const U&>)
12521242constexpr optional<T&>::optional(const optional<U>& rhs) noexcept (std::is_nothrow_constructible_v<T&, const U&>) {
12531243 if (rhs.has_value ()) {
1254- value_ = std::addressof (static_cast <T&>(*rhs));
1255- } else {
1256- value_ = nullptr ;
1244+ convert_ref_init_val (*rhs);
12571245 }
12581246}
12591247
@@ -1263,9 +1251,7 @@ template <class U>
12631251 !std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
12641252constexpr optional<T&>::optional(optional<U>&& rhs) noexcept (noexcept (std::is_nothrow_constructible_v<T&, U>)) {
12651253 if (rhs.has_value ()) {
1266- value_ = std::addressof (static_cast <T&>(*std::move (rhs)));
1267- } else {
1268- value_ = nullptr ;
1254+ convert_ref_init_val (*std::move (rhs));
12691255 }
12701256}
12711257
@@ -1276,9 +1262,7 @@ template <class U>
12761262constexpr optional<T&>::optional(const optional<U>&& rhs) noexcept (
12771263 noexcept (std::is_nothrow_constructible_v<T&, const U>)) {
12781264 if (rhs.has_value ()) {
1279- value_ = std::addressof (static_cast <T&>(*std::move (rhs)));
1280- } else {
1281- value_ = nullptr ;
1265+ convert_ref_init_val (*std::move (rhs));
12821266 }
12831267}
12841268
@@ -1293,7 +1277,7 @@ template <class T>
12931277template <class U >
12941278 requires (std::is_constructible_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
12951279constexpr T& optional<T&>::emplace(U&& u) noexcept (std::is_nothrow_constructible_v<T&, U>) {
1296- value_ = std::addressof ( static_cast <T&>( std::forward<U>(u) ));
1280+ convert_ref_init_val ( std::forward<U>(u));
12971281 return *value_;
12981282}
12991283
@@ -1338,21 +1322,15 @@ constexpr bool optional<T&>::has_value() const noexcept {
13381322
13391323template <class T >
13401324constexpr T& optional<T&>::value() const {
1341- if (has_value ())
1342- return *value_;
1343- throw bad_optional_access ();
1325+ return has_value () ? *value_ : throw bad_optional_access ();
13441326}
13451327
13461328template <class T >
13471329template <class U >
13481330constexpr std::remove_cv_t <T> optional<T&>::value_or(U&& u) const {
13491331 static_assert (std::is_constructible_v<std::remove_cv_t <T>, T&>, " T must be constructible from a T&" );
13501332 static_assert (std::is_convertible_v<U, std::remove_cv_t <T>>, " Must be able to convert u to T" );
1351- if (has_value ()) {
1352- return std::remove_cv_t <T>(*value_);
1353- } else {
1354- return std::forward<U>(u);
1355- }
1333+ return has_value () ? *value_ : static_cast <std::remove_cv_t <T>>(std::forward<U>(u));
13561334}
13571335
13581336// \rSec3[optionalref.monadic]{Monadic operations}
@@ -1370,7 +1348,7 @@ constexpr auto optional<T&>::and_then(F&& f) const {
13701348
13711349template <class T >
13721350template <class F >
1373- constexpr auto optional<T&>::transform(F&& f) const -> optional<std:: invoke_result_t <F, T&>> {
1351+ constexpr optional<std:: invoke_result_t <F, T&>> optional<T&>::transform(F&& f) const {
13741352 using U = std::invoke_result_t <F, T&>;
13751353 static_assert (!std::is_same_v<std::remove_cvref_t <U>, in_place_t >, " Result must not be in_place_t" );
13761354 static_assert (!std::is_same_v<std::remove_cvref_t <U>, nullopt_t >, " Result must not be nullopt_t" );
@@ -1387,7 +1365,7 @@ template <class T>
13871365template <class F >
13881366constexpr optional<T&> optional<T&>::or_else(F&& f) const {
13891367 using U = std::invoke_result_t <F>;
1390- static_assert (std::is_same_v<std::remove_cvref_t <U>, optional>);
1368+ static_assert (std::is_same_v<std::remove_cvref_t <U>, optional>, " Result must be an optional " );
13911369 if (has_value ()) {
13921370 return *value_;
13931371 } else {
0 commit comments