From: Jonathan Wakely Date: Wed, 22 Apr 2026 14:37:16 +0000 (+0100) Subject: libstdc++: Constrain tuple(tuple&&) [PR78302] X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5154144864a669c722fbb2170e79416c3ae5ff50;p=thirdparty%2Fgcc.git libstdc++: Constrain tuple(tuple&&) [PR78302] Since C++20 the std::tuple move constructor should be constrained (as modified by LWG 2899). We already define the move constructor as defaulted, but it's not implicitly defined as deleted for non-move-constructible element types because the _Tuple_impl(_Tuple_impl&&) constructor is user-provided and unconstrained. For C++20 and later we use a requires-clause to constrain the defaulted tuple(tuple&&) constructor. Ideally we'd make this change pre-C++20 as well, but that's harder to do without using a requires-clause, so this change is only for C++20 and later. I think that's OK, but if we need to change it for pre-C++20 later we can consider inheriting from _Enable_copy_move<..., tuple> to make the defaulted move constructor defined as deleted. libstdc++-v3/ChangeLog: PR libstdc++/78302 PR libstdc++/71301 * include/std/tuple [C++20] (tuple(tuple&&)): Add requires-clause. * testsuite/20_util/tuple/cons/78302.cc: New test. Reviewed-by: Tomasz KamiƄski --- diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index cbacd5a3c97..64b96fe4f59 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -954,7 +954,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr tuple(const tuple&) = default; - constexpr tuple(tuple&&) = default; + constexpr + tuple(tuple&&) requires (is_move_constructible_v<_Elements> && ...) + = default; template requires (__constructible()) diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc new file mode 100644 index 00000000000..6998a9e418a --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc @@ -0,0 +1,17 @@ +// { dg-do compile { target c++20 } } + +// Bug 78302 is_move_constructible_v> should be false +// LWG 2899. is_(nothrow_)move_constructible and tuple, optional and unique_ptr + +#include +#include + +struct NotMovable { NotMovable(NotMovable&&) = delete; }; +static_assert(!std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); +static_assert(!std::is_move_constructible_v>); +static_assert(std::is_nothrow_move_constructible_v>); +static_assert(std::is_nothrow_move_constructible_v>); +static_assert(std::is_nothrow_move_constructible_v>); +static_assert(std::is_nothrow_move_constructible_v>);