From: Tomasz Kamiński Date: Mon, 27 Oct 2025 13:19:47 +0000 (+0100) Subject: libstdc++: Implement const copy-assignment for tuple<> [PR119721] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8728f60b9750ea10abd1a02db7972a6ff6ef2eae;p=thirdparty%2Fgcc.git libstdc++: Implement const copy-assignment for tuple<> [PR119721] This patch completes the implementation of P2321R2, giving tuple proper proxy reference semantics. The assignment operator is implemented as a template constrained to accept only tuple<>. Consequently, the language does not consider it a copy assignment operator, which prevents tuple<> from losing its trivially copyable status. The _Tuple template parameter is defaulted, ensuring the operator remains a viable candidate for assignment with an empty brace-init list. PR libstdc++/119721 libstdc++-v3/ChangeLog: * include/std/tuple (tuple<>::operator=(const _Tuple&) const) [__cpp_lib_ranges_zip]: Define. * testsuite/23_containers/tuple/cons/119721.cc: Test const assignment. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 6edcf5e5553..d4db12557ab 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -1996,6 +1996,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void swap(tuple&) noexcept { /* no-op */ } #if __cpp_lib_ranges_zip // >= C++23 + template _Tuple = tuple> + constexpr const tuple& + operator=(const _Tuple&) const noexcept + { return *this; } + constexpr void swap(const tuple&) const noexcept { /* no-op */ } #endif diff --git a/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc b/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc index 240f1a5e8d7..1d152386fb7 100644 --- a/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc +++ b/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc @@ -69,12 +69,22 @@ test04() { std::array a{}; const std::tuple<> t1; - + // Const assignment from array - t1 = a; - t1 = std::move(a); - - VERIFY( t1 == a ); + std::tuple<> t2; + const std::tuple<>& r1 = (t1 = t2); + VERIFY( &r1 == &t1 ); + const std::tuple<>& r2 = (t1 = std::move(t2)); + VERIFY( &r2 == &t1 ); + + const std::tuple<>& r3 = (t1 = {}); + VERIFY( &r3 == &t1 ); + + // Const assignment from array + const std::tuple<>& r4 = (t1 = a); + VERIFY( &r4 == &t1 ); + const std::tuple<>& r5 = (t1 = std::move(a)); + VERIFY( &r5 == &t1 ); } void