https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121748
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Tomasz Kaminski <[email protected]>: https://gcc.gnu.org/g:23657d3972605542b02a33e67edcc74a7eede02c commit r16-4552-g23657d3972605542b02a33e67edcc74a7eede02c Author: Giuseppe D'Angelo <[email protected]> Date: Wed Oct 22 09:31:46 2025 +0200 libstdc++: Implement optional<T&> from P2988R12 [PR121748] This patch implements optional<T&> based on the P2988R12 paper, incorporating corrections from LWG4300, LWG4304, and LWG3467. The resolution for LWG4015 is also extended to cover optional<T&>. We introduce _M_fwd() helper, that is equivalent to operator*(), except that it does not check non-empty precondition. It is used in to correctly propagate the value during move construction from optional<T&>. This is necessary because moving an optional<T&> must not move the contained object, which is the key distinction between *std::move(opt) and std::move(*opt). The implementation deviates from the standard by providing a separate std::swap overload for std::optional<T&>, which simplifies preserving the resolution of LWG2766. This introduces a few changes to make_optional behavior (see included test): * some previously valid uses of make_optional<T>({...}) (where T is not a reference type) now become ill-formed (see optional/make_optional_neg.cc). * make_optional<T&>(t) and make_optional<const T&>(ct), where decltype(t) is T&, and decltype(ct) is const T& now produce optional<T&> and optional<const T&> respectively, instead of optional<T>. * a few other uses of make_optional<R> with reference type R are now ill-formed. PR libstdc++/121748 libstdc++-v3/ChangeLog: * include/bits/version.def: Bump value for optional, * include/bits/version.h: Regenerate. * include/std/optional (std::__is_valid_contained_type_for_optional): Define. (std::optional<T>): Use __is_valid_contained_type_for_optional. (optional<T>(const optional<_Up>&), optional<T>(optional<_Up>&&)) (optional<T>::operator=(const optional<_Up>&)) (optional<T>::operator=(optional<_Up>&&)): Replacex._M_get() with x._M_fwd(), and std::move(x._M_get()) with std::move(x)._M_fwd(). (optional<T>::and_then): Remove uncessary remove_cvref_t. (optional<T>::_M_fwd): Define. (std::optional<T&>): Define new partial specialization. (std::swap(std::optional<T&>, std::optional<T&>)): Define. (std::make_optional(_Tp&&)): Add non-type template parameter. (std::make_optional): Use parenthesis to constructor optional. (std::hash<optional<T>>): Add comment. * testsuite/20_util/optional/make_optional-2.cc: Guarded not longer working example. * testsuite/20_util/optional/relops/constrained.cc: Expand test to cover optionals of reference. * testsuite/20_util/optional/requirements.cc: Ammend for optional<T&>. * testsuite/20_util/optional/requirements_neg.cc: Likewise. * testsuite/20_util/optional/version.cc: Test new value of __cpp_lib_optional. * testsuite/20_util/optional/make_optional_neg.cc: New test. * testsuite/20_util/optional/monadic/ref_neg.cc: New test. * testsuite/20_util/optional/ref/access.cc: New test. * testsuite/20_util/optional/ref/assign.cc: New test. * testsuite/20_util/optional/ref/cons.cc: New test. * testsuite/20_util/optional/ref/internal_traits.cc: New test. * testsuite/20_util/optional/ref/make_optional/1.cc: New test. * testsuite/20_util/optional/ref/make_optional/from_args_neg.cc: New test. * testsuite/20_util/optional/ref/make_optional/from_lvalue_neg.cc: New test. * testsuite/20_util/optional/ref/make_optional/from_rvalue_neg.cc: New test. * testsuite/20_util/optional/ref/monadic.cc: New test. * testsuite/20_util/optional/ref/relops.cc: New test. Reviewed-by: Jonathan Wakely <[email protected]> Co-authored-by: Tomasz KamiÅski <[email protected]>
