@@ -49,6 +49,12 @@ template <typename T, typename U>
4949concept optional_ge_rel = requires (const T& t, const U& u) {
5050 { t >= u } -> std::convertible_to<bool >;
5151};
52+
53+ struct from_function_t {
54+ explicit from_function_t () = default;
55+ };
56+
57+ inline constexpr from_function_t from_function{};
5258} // namespace detail
5359
5460struct in_place_t {
@@ -403,6 +409,13 @@ class optional {
403409 std::destroy_at (std::addressof (value_));
404410 engaged_ = false ;
405411 }
412+
413+ template <class U >
414+ friend class optional ;
415+
416+ template <class F , class Arg >
417+ constexpr optional (detail::from_function_t , F&& f, Arg&& arg)
418+ : value_(std::invoke(std::forward<F>(f), std::forward<Arg>(arg))), engaged_(true ) {}
406419};
407420
408421class bad_optional_access : public std ::exception {
@@ -785,7 +798,7 @@ constexpr auto optional<T>::transform(F&& f) & {
785798 static_assert (!std::is_same_v<U, in_place_t >);
786799 static_assert (!std::is_same_v<U, nullopt_t >);
787800 static_assert (std::is_object_v<U> || std::is_reference_v<U>); // / References now allowed
788- return (has_value ()) ? optional<U>{std::invoke ( std::forward<F>(f), value_) } : optional<U>{};
801+ return (has_value ()) ? optional<U>{detail::from_function, std::forward<F>(f), value_} : optional<U>{};
789802}
790803
791804template <class T >
@@ -796,7 +809,7 @@ constexpr auto optional<T>::transform(F&& f) && {
796809 static_assert (!std::is_same_v<U, in_place_t >);
797810 static_assert (!std::is_same_v<U, nullopt_t >);
798811 static_assert (std::is_object_v<U> || std::is_reference_v<U>); // / References now allowed
799- return (has_value ()) ? optional<U>{std::invoke ( std::forward<F>(f), std::move (value_) )} : optional<U>{};
812+ return (has_value ()) ? optional<U>{detail::from_function, std::forward<F>(f), std::move (value_)} : optional<U>{};
800813}
801814
802815template <class T >
@@ -807,7 +820,7 @@ constexpr auto optional<T>::transform(F&& f) const& {
807820 static_assert (!std::is_same_v<U, in_place_t >);
808821 static_assert (!std::is_same_v<U, nullopt_t >);
809822 static_assert (std::is_object_v<U> || std::is_reference_v<U>); // / References now allowed
810- return (has_value ()) ? optional<U>{std::invoke ( std::forward<F>(f), value_) } : optional<U>{};
823+ return (has_value ()) ? optional<U>{detail::from_function, std::forward<F>(f), value_} : optional<U>{};
811824}
812825
813826template <class T >
@@ -818,7 +831,7 @@ constexpr auto optional<T>::transform(F&& f) const&& {
818831 static_assert (!std::is_same_v<U, in_place_t >);
819832 static_assert (!std::is_same_v<U, nullopt_t >);
820833 static_assert (std::is_object_v<U> || std::is_reference_v<U>); // / References now allowed
821- return (has_value ()) ? optional<U>{std::invoke ( std::forward<F>(f), value_)} : optional<U>{};
834+ return (has_value ()) ? optional<U>{detail::from_function, std::forward<F>(f), std::move ( value_)} : optional<U>{};
822835}
823836
824837// / Calls `f` if the optional is empty
@@ -1207,6 +1220,14 @@ class optional<T&> {
12071220 T& r (std::forward<U>(u));
12081221 value_ = std::addressof (r);
12091222 }
1223+
1224+ template <class U >
1225+ friend class optional ;
1226+
1227+ template <class F , class Arg >
1228+ constexpr optional (detail::from_function_t , F&& f, Arg&& arg) {
1229+ convert_ref_init_val (std::invoke (std::forward<F>(f), std::forward<Arg>(arg)));
1230+ }
12101231};
12111232
12121233// \rSec3[optionalref.ctor]{Constructors}
@@ -1356,7 +1377,7 @@ constexpr optional<std::invoke_result_t<F, T&>> optional<T&>::transform(F&& f) c
13561377 static_assert ((std::is_object_v<U> && !std::is_array_v<U>) || std::is_lvalue_reference_v<U>,
13571378 " Result must be an non-array object or an lvalue reference" );
13581379 if (has_value ()) {
1359- return optional<U>{std::invoke ( std::forward<F>(f), *value_) };
1380+ return optional<U>{detail::from_function, std::forward<F>(f), *value_};
13601381 } else {
13611382 return optional<U>{};
13621383 }
@@ -1368,7 +1389,7 @@ constexpr optional<T&> optional<T&>::or_else(F&& f) const {
13681389 using U = std::invoke_result_t <F>;
13691390 static_assert (std::is_same_v<std::remove_cvref_t <U>, optional>, " Result must be an optional" );
13701391 if (has_value ()) {
1371- return *value_ ;
1392+ return *this ;
13721393 } else {
13731394 return std::forward<F>(f)();
13741395 }
0 commit comments