Skip to content

Commit 7d00f7e

Browse files
committed
Add constraint to emplace, add deleted optional<T&> constructors, add tests
1 parent 153e7e9 commit 7d00f7e

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

libcxx/include/optional

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ namespace std {
240240
# include <__type_traits/is_trivially_relocatable.h>
241241
# include <__type_traits/is_unbounded_array.h>
242242
# include <__type_traits/negation.h>
243+
# include <__type_traits/reference_constructs_from_temporary.h>
243244
# include <__type_traits/remove_const.h>
244245
# include <__type_traits/remove_cv.h>
245246
# include <__type_traits/remove_cvref.h>
@@ -265,6 +266,11 @@ namespace std {
265266
_LIBCPP_PUSH_MACROS
266267
# include <__undef_macros>
267268

269+
# if _LIBCPP_STD_VER >= 26
270+
# define _LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_TP, _UP) \
271+
requires(is_lvalue_reference_v<_TP> && reference_constructs_from_temporary_v<_TP, _UP>)
272+
# endif
273+
268274
namespace std // purposefully not using versioning namespace
269275
{
270276

@@ -813,6 +819,41 @@ public:
813819
this->__construct_from(std::move(__v));
814820
}
815821

822+
// deleted optional<T&> constructors
823+
# if _LIBCPP_STD_VER >= 26
824+
template <class _Up,
825+
class... _Args,
826+
enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0>
827+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
828+
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) = delete;
829+
830+
template <class _Up = value_type,
831+
enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
832+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
833+
_LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) = delete;
834+
835+
template <class _Up = remove_cv_t<_Tp>,
836+
enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
837+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
838+
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) = delete;
839+
840+
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
841+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
842+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) = delete;
843+
844+
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
845+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
846+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) = delete;
847+
848+
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
849+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
850+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) = delete;
851+
852+
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
853+
_LIBCPP_OPT_REF_DELETED_CONS_REQUIRES(_Tp, _Up)
854+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) = delete;
855+
# endif
856+
816857
# if _LIBCPP_STD_VER >= 23
817858
template <class _Tag,
818859
class _Fp,
@@ -868,7 +909,12 @@ public:
868909

869910
template <class _Up,
870911
class... _Args,
871-
enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0>
912+
enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
913+
# if _LIBCPP_STD_VER >= 26
914+
&& !reference_constructs_from_temporary_v<_Tp&, _Up>
915+
# endif
916+
,
917+
int> = 0>
872918
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
873919
reset();
874920
this->__construct(__il, std::forward<_Args>(__args)...);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++26
10+
11+
// optional
12+
13+
#include <optional>
14+
#include <utility>
15+
16+
struct X {
17+
int i;
18+
19+
X(int j) : i(j) {}
20+
};
21+
22+
int main(int, char**) {
23+
const std::optional<int> _co(1);
24+
std::optional<int> _o(1);
25+
26+
// expected-error-re@*:* 8 {{call to deleted constructor of 'std::optional<{{.*}}>'}}
27+
std::optional<const int&> o1{1}; // optional(U&&)
28+
std::optional<const int&> o2{std::optional<int>(1)}; // optional(optional<U>&&)
29+
std::optional<const int&> o3{_co}; // optional(const optional<U>&)
30+
std::optional<const int&> o4{_o}; // optional(optional<U>&)
31+
std::optional<const X&> o5{1}; // optional(U&&)
32+
std::optional<const X&> o6{std::optional<int>(1)}; // optional(optional<U>&&)
33+
std::optional<const X&> o7{_co}; // optional(const optional<U>&)
34+
std::optional<const X&> o8{_o}; // optional(optional<U>&)
35+
}

0 commit comments

Comments
 (0)