[libcxx-commits] [libcxx] 57bf5dd - [libc++][tuple.apply] Implement P2255R2 make_from_tuple part. (#152867)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 19 03:14:16 PDT 2025


Author: yronglin
Date: 2025-08-19T18:14:13+08:00
New Revision: 57bf5dd7a01f87cab3d659e91a2a5dc42e8eaf53

URL: https://github.com/llvm/llvm-project/commit/57bf5dd7a01f87cab3d659e91a2a5dc42e8eaf53
DIFF: https://github.com/llvm/llvm-project/commit/57bf5dd7a01f87cab3d659e91a2a5dc42e8eaf53.diff

LOG: [libc++][tuple.apply] Implement P2255R2 make_from_tuple part. (#152867)

Implement  P2255R2 tuple.apply part wording for `std::make_from_tuple`.
```
Mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
```

Fixes #154274

---------

Signed-off-by: yronglin <yronglin777 at gmail.com>

Added: 
    libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp

Modified: 
    libcxx/include/tuple
    libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/tuple b/libcxx/include/tuple
index be30ab5b2173d..b046e2aed43e2 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1432,6 +1432,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t,
     enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr)
     _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
 #endif // _LIBCPP_STD_VER >= 20
+#undef _LIBCPP_NOEXCEPT_RETURN
 
 template <class _Tp, class _Tuple,
           class _Seq = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>, class = void>
@@ -1451,10 +1452,19 @@ template <class _Tp, class _Tuple>
 #else
 template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
 #endif // _LIBCPP_STD_VER >= 20
+
 inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
-    _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>(
-        std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))
-#    undef _LIBCPP_NOEXCEPT_RETURN
+  noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
+                    make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
+#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
+  if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
+    static_assert(!std::reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
+                  "Attempted construction of reference element binds to a temporary whose lifetime has ended");
+  }
+#endif // _LIBCPP_STD_VER >= 23
+  return std::__make_from_tuple_impl<_Tp>(
+        std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>());
+}
 
 #  endif // _LIBCPP_STD_VER >= 17
 

diff  --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
index 2c14de8c796c1..8b9e94a1c1ad9 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
@@ -286,6 +286,8 @@ LIBCPP_STATIC_ASSERT(can_make_from_tuple_impl<float, std::tuple<double>>);
 
 } // namespace LWG3528
 
+static_assert(LWG3528::can_make_from_tuple<int, std::tuple<>>);
+
 int main(int, char**)
 {
     test_constexpr_construction();

diff  --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
new file mode 100644
index 0000000000000..2dfbae9138864
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <tuple>
+
+// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
+// Mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
+
+#include <tuple>
+#include <utility>
+
+#include "test_macros.h"
+
+void test() {
+  // FreeBSD ci use clang 19.1.1, which hasn't implement __reference_constructs_from_temporary.
+  // The static_assert inner std::make_from_tuple will not triggered.
+#if __has_builtin(__reference_constructs_from_temporary)
+  // expected-error@*:* {{static assertion failed}}
+#endif
+
+  // Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5).
+#if TEST_STD_VER >= 26
+  // expected-error at tuple:* {{returning reference to local temporary object}}
+#else
+  // expected-warning at tuple:* {{returning reference to local temporary object}}
+#endif
+  std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
+}


        


More information about the libcxx-commits mailing list