On Wed, May 6, 2026 at 4:16 PM Jonathan Wakely <[email protected]> wrote:
> 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.
> ---
>
> Tested x86_64-linux.
>
> libstdc++-v3/include/std/tuple | 4 +++-
> libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc | 11 +++++++++++
> 2 files changed, 14 insertions(+), 1 deletion(-)
> create mode 100644 libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc
>
> diff --git a/libstdc++-v3/include/std/tuple
> b/libstdc++-v3/include/std/tuple
> index cbacd5a3c977..64b96fe4f599 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> && ...)
>
Could you add test for tuple of references (lvalue and rvalue)? I think the
traits
gives correct result, but I am not sure.
> + = default;
>
> template<typename... _UTypes>
> requires (__constructible<const _UTypes&...>())
> 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 000000000000..b3c6bd67fd27
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/78302.cc
> @@ -0,0 +1,11 @@
> +// { dg-do compile { target c++20 } }
> +
> +// Bug 78302 is_move_constructible_v<tuple<nonmovable>> should be false
> +// LWG 2899. is_(nothrow_)move_constructible and tuple, optional and
> unique_ptr
> +
> +#include <tuple>
> +#include <type_traits>
> +
> +struct NotMovable { NotMovable(NotMovable&&) = delete; };
> +static_assert(!std::is_move_constructible_v<std::tuple<NotMovable>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::tuple<int>>);
> --
> 2.54.0
>
>