diff --git a/stl/inc/tuple b/stl/inc/tuple index ab3952ad1da..49492bda9cd 100644 --- a/stl/inc/tuple +++ b/stl/inc/tuple @@ -132,8 +132,17 @@ template struct _Tuple_perfect_val : true_type {}; template -struct _Tuple_perfect_val<_Myself, _This2> - : bool_constant>>> {}; +struct _Tuple_perfect_val<_Myself, _This2> : bool_constant>> {}; + +template +struct _Tuple_perfect_val, _Uty0, _Uty1> + : bool_constant, allocator_arg_t>>, + is_same<_Remove_cvref_t<_Ty0>, allocator_arg_t>>> {}; + +template +struct _Tuple_perfect_val, _Uty0, _Uty1, _Uty2> + : bool_constant, allocator_arg_t>>, + is_same<_Remove_cvref_t<_Ty0>, allocator_arg_t>>> {}; struct _Ignore { // struct that ignores assignments template diff --git a/tests/std/test.lst b/tests/std/test.lst index 2a8cf5e9ac2..217244f3f91 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -198,6 +198,7 @@ tests\GH_002488_promise_not_default_constructible_types tests\GH_002581_common_reference_workaround tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function +tests\LWG3121_constrained_tuple_forwarding_ctor tests\LWG3146_excessive_unwrapping_ref_cref tests\LWG3422_seed_seq_ctors tests\LWG3480_directory_iterator_range diff --git a/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/env.lst b/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/test.cpp b/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/test.cpp new file mode 100644 index 00000000000..f421d2e583c --- /dev/null +++ b/tests/std/tests/LWG3121_constrained_tuple_forwarding_ctor/test.cpp @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#if _HAS_CXX20 +#define CONSTEXPR_VAR_20 constexpr +#else +#define CONSTEXPR_VAR_20 const +#endif + +using namespace std; + +class pseudo_any { +private: + bool has_value_ = false; + +public: + pseudo_any() = default; + template , pseudo_any>>, is_copy_constructible>>, + int> = 0> + constexpr pseudo_any(ValT&&) noexcept : has_value_{true} {} + + constexpr bool has_value() const noexcept { + return has_value_; + } +}; + +STATIC_ASSERT(is_copy_constructible_v>); + +using TA2 = tuple; +using TA3 = tuple; + +CONSTEXPR_VAR_20 TA2 t2{allocator_arg, allocator{}}; +CONSTEXPR_VAR_20 TA3 t3{allocator_arg, allocator{}, tuple{}}; + +#if _HAS_CXX20 +static_assert(!get<0>(t2).has_value()); +static_assert(!get<1>(t2).has_value()); +static_assert(!get<0>(t3).has_value()); +static_assert(!get<1>(t3).has_value()); +static_assert(get<2>(t3).has_value()); +#endif // _HAS_CXX20 + +int main() { + assert(!get<0>(t2).has_value()); + assert(!get<1>(t2).has_value()); + assert(!get<0>(t3).has_value()); + assert(!get<1>(t3).has_value()); + assert(get<2>(t3).has_value()); +}