diff --git a/libcxx/include/tuple b/libcxx/include/tuple --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -883,13 +883,13 @@ template &>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr - explicit(!(is_convertible_v<_Up&, _Tp> && ...)) + explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t) : __base_(__t) {} template &>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr - explicit(!(is_convertible_v<_Up&, _Tp> && ...)) + explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value) tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t) : __base_(allocator_arg_t(), __alloc, __t) {} #endif // _LIBCPP_STD_VER >= 23 @@ -947,13 +947,13 @@ template &&>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr - explicit(!(is_convertible_v && ...)) + explicit(!_Lazy<_And, is_convertible...>::value) tuple(const tuple<_Up...>&& __t) : __base_(std::move(__t)) {} template &&>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr - explicit(!(is_convertible_v && ...)) + explicit(!_Lazy<_And, is_convertible...>::value) tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t) : __base_(allocator_arg_t(), __alloc, std::move(__t)) {} #endif // _LIBCPP_STD_VER >= 23 diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp @@ -15,11 +15,31 @@ #include #include +#include "test_macros.h" + template constexpr void CreateTuple(std::index_sequence) { - std::tuple tuple(I...); - assert(std::get<0>(tuple) == 0); - assert(std::get(tuple) == sizeof...(I)-1); + using LargeTuple = std::tuple...>; + using TargetTuple = std::tuple; + LargeTuple tuple(std::integral_constant{}...); + assert(std::get<0>(tuple).value == 0); + assert(std::get(tuple).value == sizeof...(I)-1); + + TargetTuple t1 = tuple; // converting copy constructor from & + TargetTuple t2 = static_cast(tuple); // converting copy constructor from const& + TargetTuple t3 = std::move(tuple); // converting rvalue constructor + TargetTuple t4 = static_cast(tuple); // converting const rvalue constructor + TargetTuple t5; // default constructor + (void)t1; (void)t2; (void)t3; (void)t4; (void)t5; + +#if TEST_STD_VER >= 20 + t1 = tuple; // converting assignment from & + t1 = static_cast(tuple); // converting assignment from const& + t1 = std::move(tuple); // converting assignment from && + t1 = static_cast(tuple); // converting assignment from const&& + swap(t1, t2); // swap +#endif + // t1 == tuple; // comparison does not work yet (we blow the constexpr stack) } constexpr bool test() {